Using the native payment request JavaScript API

I'm a full-stack developer from South Africa πΏπ¦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa πΏπ¦. I love writing about JavaScript, HTML and CSS.
Great article Chris Bongers. Didn't know that it was even a thing in JavaScript :). Thanks for sharing!
Yeah was quite surprised to find this, and super happy to see the JavaScript native ecosystem growing like this.
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

The other day I was browsing some articles. In one of these articles, they described the Payment Request API. At that point, I'd never heard of it before, but it sparked my interest.
Whenever we build websites that allow people to pay for something, we enter a new level of difficulty.
(Luckily, Stripe and others have made this a little bit easier)
But how cool would it be if it was simply an API in the browser? π€
Our prayers seem to have been heard as we now get access to the Payment Request API.
In the video below, you see a complete experience for the end user.

First, it's good to note that the Payment Request API is not a new way of paying for stuff. It's instead an optimized flow for both the consumer and the merchant to have a seamless native experience when paying online.
The experience with the payment request flow is that the consumer no longer has to fill out multiple forms containing all kinds of details.
They instead leverage what is already set up in their browser. And this makes total sense, right.
Why would I need to fill out my shipping address on every website, it rarely changes, and the same goes for personal details.
So why not leverage this in the browser!
Let's see how we can use this Payment Request API in our application.
For this demo, I'll simulate a donation button where people can donate one dollar because they love the content.
A second note is that you can leverage Bobbucks when testing this out. This is an app that helps to process demo payments.
Let's create our sample button and a text box with some information for the user.
<button id="checkout">Donate 1$</button>
<div id="response">You won't be actually charged, give it a test drive π€</div>
We must attach a click handler to the button to start the payment process.
button.addEventListener('click', () => {
// Do something
});
The next step is to start setting up the payment request. In its most basic form, it looks like this:
const request = new PaymentRequest(paymentMethods, paymentDetails);
The payment methods can contain a list of supported payment methods. Each item in the object consists of two parameters.
supportedMethods: URL Based string pointing to the payment endpointdata: Optional information provided by the payment providerIf we now take Bobbucks (our demo payment provider) as an example, we can initiate that with the following context.
const paymentMethods = [
{
supportedMethods: 'https://bobbucks.dev/pay',
},
];
Bobbucks doesn't take any optional data.
The second part of the request is the data around what we are paying for.
Generally, this would most likely come from your shopping cart, but since we use a static 1$ donation, we can provide it hard-coded.
const paymentDetails = {
id: 'demo-123',
displayItems: [
{
label: 'Support for this blog',
amount: { currency: 'USD', value: '1.00' },
},
],
total: {
label: 'Total',
amount: { currency: 'USD', value: '1.00' },
},
};
Now that we have all the information let's put it into action and initiate the payment request when the user clicks the button.
button.addEventListener('click', () => {
request.show().then((paymentResponse) => {
paymentResponse.complete('success').then(() => {
response.innerText = 'Thanks for your donation π';
});
});
});
Now click the button, and you should see the magic happen πͺ.
It's good to note that although this API handles all the payment magic, you still need to handle the payment on your side.
In this demo, we don't go into detail about that, but it's up to you to integrate some server-side validation of whether the payment was successful and what data you need to process based on the response.
To showcase a response, it's available as the return object from the show method.
button.addEventListener('click', () => {
request.show().then((paymentResponse) => {
console.log(paymentResponse);
// Handle payment before showing the success!
paymentResponse.complete('success').then(() => {
response.innerText = 'Thanks for your donation π';
});
});
});
This response object will look something like this.
details: {bobbucks_token_id: 'ABCDEADBEEF', message: 'Thanks for using BobBucks!'}
methodName: "https://bobbucks.dev/pay"
onpayerdetailchange: null
payerEmail: null
payerName: null
payerPhone: null
requestId: "demo-123"
shippingAddress: null
shippingOption: null
So far, we have played around with Bobbucks since it's a super easy way to test this API.
But what happens if we enter a real-world scenario, we often want to give the user multiple payment provider options.
Let's take Google Pay, for instance. Luckily for us, Google Pay also has a demo mode that we can use to test it out.
As mentioned in the beginning, the payment methods can accept multiple providers.
Let's add Google Pay to it.
const paymentMethods = [
{
supportedMethods: 'https://bobbucks.dev/pay',
},
{
supportedMethods: 'https://google.com/pay',
},
];
Remember I told you about the different data objects we can provide? Well, Google Pay is one of those providing us with this object.
You can find the entire object on the Google documentation website.
But in general, it would look something like this.
const paymentMethods = [
{
supportedMethods: 'https://bobbucks.dev/pay',
},
{
supportedMethods: 'https://google.com/pay',
data: {
environment: 'TEST',
apiVersion: 2,
apiVersionMinor: 0,
merchantInfo: {
// merchantId: '12345678901234567890',
merchantName: 'Example Merchant',
},
allowedPaymentMethods: [
{
type: 'CARD',
parameters: {
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
allowedCardNetworks: [
'AMEX',
'DISCOVER',
'INTERAC',
'JCB',
'MASTERCARD',
'MIR',
'VISA',
],
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'example',
gatewayMerchantId: 'exampleGatewayMerchantId',
},
},
},
],
},
},
];
Quite a chunk of data, I won't be going into details, but it tells Google Pay which methods you accept and how you want the payment to be handled.
Now, if we re-open our payment, we should get an intermediate step where we get the option to choose which payment provider we want to use.

So far, we only require people to pay. We don't care about any details.
But what happens if we have a product that needs shipping? Or do we want to know the user's email address so we can send them our e-book?
Well, that's where we can use the payment options for.
This is where we can set the third option on the payment request constructor.
const paymentOptions = {
requestPayerName: true,
requestPayerEmail: true,
requestPayerPhone: true,
requestShipping: true,
shippingType: 'shipping',
};
const request = new PaymentRequest(
paymentMethods,
paymentDetails,
paymentOptions
);
Now when we click the payment button, we see some extra options we have to fill out before we can continue.

I'm sure this is the part most of you were waiting for, a demo to try it out yourself.
Feel free to test this CodePen. (You won't be charged, and you can use Bobbucks to simulate a payment)
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter