Getting Paid with the Payment-Request API

This post first appeared on the Samsung Internet blog pages

The whirlwind of 2020 has blown many people out of work and steady employment. It’s also brought with it uprisings, protests and I’m sure we’re on the verge of a revolution somewhere 👀. But with these changes, there have also been people dedicating more time to their side-hustles, new organisations dedicated to activism and community good, and more established organisations who’ve seen a boom in their donations this year. While many will rely on a combination of direct bank/PayPal transfer or whatever payment processor comes with their site builder, some will need to roll out their own payment processing. This is exactly the situation Laura and I found ourselves in as we’re building out the Samsung Global Goals PWA and this is where the Payment Request API comes into play.

The Payment Request API is a secure way to collect payments from users without having to collect and store any of their personal details yourself (this is subject to regional laws, make surer you’re following regulation when handling customer data and money), it “provides a consistent user experience for both merchants and users”. You’ve likely used this API when you bought those cute masks on Etsy and paid with Samsung/Google/Apple pay. On a desktop web browser, the API will use the browser’s cards however, in a mobile browser the API will use Google/Samsung Pay instead. This is what that looks like:

The payment API form generated on a desktop browser, the form appears as a dropdown from the address bar The payment API form generated on a mobile browser, the form fills up the screen

A Basic Setup

You absolutely should be using a payment processor and shouldn’t be rolling out your own, so for this I’m using Stripe. Stripe does a good job of abstracting a lot of the nitty gritty of the Payment Request API but still keeps some of the key functions. This basic set up took me a moment to get my head around because of the back and forth between the server and the client. Considering we’ve had enough confusion to last two lifetimes this year, I thought to break the process down and share it.

  1. First create and show the payment request in the client, this brings up the form.
/* CLIENT */const paymentRequest = **_stripe_**.paymentRequest({
    country: 'GB',
    currency: 'gbp',
    total: {
        label: 'Donation',
        amount: 100,
    },
    requestPayerName: true,
    requestPayerEmail: true
});await paymentRequest.canMakePayment()
paymentRequest.show();
  1. In the server, create a Stripe payment intent and send the client secret from the intent to client
/* SERVER */app.get('/payment/', async(req,res)=>{    const paymentIntent = await stripe.paymentIntents.create({
        amount: 100,
        currency: 'gbp',
        payment_method_types: ['card']
    });    res.send({clientSecret: paymentIntent.client_secret});})
  1. Use the payment intent’s client secret to confirm the card payment
/* CLIENT */const fetchedClientSecret = await fetch(`/payment`);
const clientSecretObj = await fetchedClientSecret.json();paymentRequest.on('paymentmethod', async (ev) => {
 
    const {paymentIntent, error: confirmError} = await **_stripe_**.confirmCardPayment(
        clientSecretObj.clientSecret,
        {payment_method: ev.paymentMethod.id},
        {handleActions: false}
    );    if (confirmError) {
        ev.complete('fail');
    } else {
        ev.complete('success');
    }
});

What do You Get Out of it?

The greatest benefit of the Payment Request API is that it simplifies the payment flow while also ensuring security, but there are more reasons:

const paymentRequest = stripe.paymentRequest({
    ...    **requestPayerName: true,
    requestPayerEmail: true**
});

Limitations

In Summary…

I’m a convert and I hope you are too. The Payment Request API does a lot of heavy lifting so you don’t have to, paired with a good payment processor then you really don’t have to worry about collecting secure payments that are easily traceable (for audits) and stored safely.

Further Reading