Declarative internet shopping with Payment Request API and Angular
By: Roman Sedov
Tags: Angular, JavaScript, Open Source, API, Payments

AngularInDepth is moving away from Medium. This article, its updates and more recent articles are hosted on the new platform inDepth.dev

Remember last time you pay on a website in one touch with Google Pay, Apple Pay or a card?

For me, it is not a frequent case.

On the contrary, each new internet store offers me a new payment form. I must search for my card and write down all the information from it. Next time when I want to pay in another store, I repeat the process.

It is not convenient. But there is an alternative. A browser standard Payment Request API solves this problem in modern browsers in the last two years with ease.

Let’s see how we can implement it in Angular

What is it?

Almost all modern browsers implement Payment Request API standard. It allows calling a modal in a browser where a user can pay in a few seconds. For example, it looks like this in Chrome:

Sorry for my Russian, dudes

And the second screenshot is from Safari when paying with a fingerprint using Apple Pay:

It is as fast, as featureful. A modal shows information about the whole order and about each item inside. It can ask a user for some details about him or her. For example, email, phone number or shipping address. It is well customizable although the API ease of use is questionable.

How can we implement it in Angular?

Angular does not have any abstractions over the Payment Request API. We can inject a Document token from DI scope, get Window object from Document and work with window.PaymentRequest. It is the safest way to use it.

If you use Payment Request without abstractions, you can get into trouble. Testing the code is harder, it does not work in SSR, because there is no Payment Request and it depends on a global object.

We can use WINDOW injection token from @ng-web-apis/common to get a global object from DI safely. Now we can make a new token PAYMENT_REQUEST_SUPPORT. It will check Payment Request API support in a browser before using it. Then the situation when you try to call unsupported API will never happen.

An example of using in a service

Let’s do it the Angular way

Using the token that I described above, we can work with Payment Request safely enough. But it is still the “pure” browser API — we have to call a method with three parameters collecting much data together and mapping it to the right format.

But in the Angular world, we use many conveniences. Dependency Injection, services, directives, and streams allow us to do our work better. Let’s look at a declarative solution that makes using Payment Request API fast and easy.

The shopping cart in the example above is implemented with the following code:

It works due to the three Angular directives:

waPayment directive defines a scope for a new payment. It needs PaymentItem object with information about a label and a total sum of the payment

Each item of the shopping cart is a waPaymentItem directive. It is a declarative PaymentItem for your Payment

Click on the button starts a PaymentRequest modal in your browser that returns PaymentResponse or an error. waPaymentSubmit directive emits both these events.

This way we have a simple and convenient interface for making a payment and handling its final result. And it works in a true Angular way!

The directives are connected together:

The payment directive collects all payment items inside itself using ContentChildren. It also implements PaymentDetailsInit — one of the required arguments to call a Payment Request.

The output-directive is listening clicks on the button and emits the final payment result. It gets a payment directive from DI and also payment methods and additional payment options that we provide in DI

The whole solution

We collected all these ideas and implement it in a library @ng-web-apis/payment-request.

Here you can find a Github repository with all code

And here is a demo sample that I used to make screenshots and GIF’s for this article

It is ready to use solution that allows you to work with Payment Request API safely and fast using a service or directives.

The library is published and supported by @ng-web-apis. It is an opensource group that specializes in idiomatic lightweight implementations of native Web API’s in Angular. On our website you can find other APIs that Angular does not support out-of-the-box such as Web Audio, Web MIDI and Geolocation.