published: 30 Sep 2022
2 min read
Working with JavaScript Payment Request API
The Payment Request API is a new JavaScript API that provides a cross-browser standard to collect a payment, address, and contact information from customers that can be used to process an order.
It also facilitates the exchange of this information between the browser and the website. The fundamental idea behind this is to improve the user's online shopping experience by making it easy for users to store payment and contact information in the browser.
Browser Support
The Payment Request API is still in active development and is only supported by the last few versions of modern browsers. Before we start making a payment request, we should feature detect to ensure that the API is supported by the browser:
if (window.PaymentRequest) {
// Yes, we can use the API
} else {
// No, fallback to the checkout page
window.location.href = '/checkout'
}
Note: You can only use the Payment Request API on sites serving over
https
.
PaymentRequest
Object
A payment request is always started by creating a new object of PaymentRequest
- using the PaymentRequest()
constructor. The constructor takes two mandatory parameters and one optional parameter:
paymentMethods
defines which forms of payment are accepted. For example, you may only accept Visa and MasterCard credit cards.paymentDetails
contains the total payment amount due, taxes, shipping cost, display items, etc.options
is an optional argument used to request additional details from the user, such as name, email, phone, etc.
Let's create a new payment request with only the required parameters:
const paymentMethods = [
{
supportedMethods: ['basic-card']
}
]
const paymentDetails = {
total: {
label: 'Total Amount',
amount: {
currency: 'USD',
value: 8.49
}
}
}
const paymentRequest = new PaymentRequest(paymentMethods, paymentDetails)
Notice the supportedMethods
parameter in paymentMethods
object. When it is set to basic-card
, both debit and credit cards of all networks will be accepted. However, we can limit the supported networks and types of cards. For example, with the following only Visa, MasterCard, and Discover credit cards are accepted:
const paymentMethods = [
{
supportedMethods: ['basic-card'],
data: {
supportedNetworks: ['visa', 'mastercard', 'discover'],
supportedTypes: ['credit']
}
}
]
// ...
Payment Details
The second parameter passed to the PaymentRequest
constructor is the payment details object. It contains the total of the order and an optional array of display items. The total
parameter must include a label
parameter and an amount
parameter with currency
and value
.
You can also add additional display items to provide a high-level breakdown of the total:
const paymentDetails = {
total: {
label: 'Total Amount',
amount: {
currency: 'USD',
value: 8.49
}
},
displayItems: [
{
label: '15% Discount',
amount: {
currency: 'USD',
value: -1.49
}
},
{
label: 'Tax',
amount: {
currency: 'USD',
value: 0.79
}
}
]
}
The displayItems
parameter is not meant to display a long list of items. Since space is limited for the browser's payment UI on mobile devices, you should use this to display only top-level fields such as subtotal, discount, tax, shipping cost, etc.
The
PaymentRequest
API does not perform any calculations. So, your web application is responsible for providing the pre-calculatedtotal
amount.
Requesting Additional Details
The third optional parameter can be used to request additional information from the user, such as name, email address, and phone number:
// ...
const options = {
requestPayerName: true,
requestPayerPhone: true,
requestPayerEmail: true
}
const paymentRequest = new PaymentRequest(paymentMethods, paymentDetails, options)
By default, all of these values are false
, but adding any of them to the options
object with a value true
will result in an extra step in the payment UI. If the user has already stored these details in the browser, they will be pre-populated.
Display Payment UI
After creating a PaymentRequest
object, you must call the show()
method to display the payment request UI to the user. The show()
method returns a promise that resolves with a PaymentResponse
object if the user has successfully filled in the details. If there is an error or the user closes the UI, the promise rejects.
// ...
const paymentRequest = new PaymentRequest(paymentMethods, paymentDetails, options)
paymentRequest
.show()
.then(paymentResponse => {
// close the payment UI
paymentResponse.complete().then(() => {
// TODO: call REST API to process the payment at the backend server
// with the data from 'paymentResponse'.
})
})
.catch(err => {
// user closed the UI or the API threw an error
console.log('Error:', err)
})
With the above code, the browser will show the payment UI to the user. Once the user has filled in the details and clicked on the 'Pay' button, you will receive a PaymentResponse
object in the show()
promise. The payment request UI is closed immediately when you call the PaymentResponse.complete()
method. This method returns a new promise so that you can call the backend server with the information collected and process the payment.
If you want to call the backend server to process the payment while the payment UI is showing a spinner, you can delay the call to complete()
. Let us create a mock function for payment processing with the backend server. It takes paymentResponse
as a parameter and returns a promise after 1.5 seconds that resolves to a JSON object:
const processPaymentWithServer = paymentResponse => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ status: true })
}, 1500)
})
}
//...
paymentRequest
.show()
.then(paymentResponse => {
processPaymentWithServer(paymentResponse).then(data => {
if (data.status) {
paymentResponse.complete('success')
} else {
paymentResponse.complete('fail')
}
})
})
.catch(err => {
console.log('Error:', err)
})
In the example above, the browser payment UI will show a processing screen until the promise returned by the processPaymentWithServer()
method is settled. We also used 'success' and 'fail' strings to tell the browser about the transaction outcome. The browser will show an error message to the user if you call complete('fail')
.
Payment Request Abort
If you want to cancel the payment request due to no activity or any other reason, you can use the PaymentRequest.abort()
method. It immediately closes the payment request UI and rejects the show()
promise.
// ...
setTimeout(() => {
paymentRequest
.abort()
.then(() => {
// aborted payment request
console.log('Payment request aborted due to no activity.')
})
.catch(err => {
// error while aborting
console.log('abort() Error: ', err)
})
}, 5000)
Conclusion
That's the end of a quick introduction to JavaScript Payment Request API. It provides a browser-based method to collect customer payment and contact information that can be sent to the backend server to process the payment.
The aim is to reduce the number of steps in completing an online payment. It makes the whole checkout process smoother by remembering the user's preferred way of paying for goods and services.
If you want to learn more about the Payment Request API, here is a good resource that discusses the main concepts and usage of the API.
Are we missing something? Help us improve this article. Reach out to us.
Working with JavaScript Payment Request API
The Payment Request API is a new JavaScript API that provides a cross-browser standard to collect a payment, address, and contact information from customers that can be used to process an order.
It also facilitates the exchange of this information between the browser and the website. The fundamental idea behind this is to improve the user's online shopping experience by making it easy for users to store payment and contact information in the browser.
Browser Support
The Payment Request API is still in active development and is only supported by the last few versions of modern browsers. Before we start making a payment request, we should feature detect to ensure that the API is supported by the browser:
if (window.PaymentRequest) {
// Yes, we can use the API
} else {
// No, fallback to the checkout page
window.location.href = '/checkout'
}
Note: You can only use the Payment Request API on sites serving over
https
.
PaymentRequest
Object
A payment request is always started by creating a new object of PaymentRequest
- using the PaymentRequest()
constructor. The constructor takes two mandatory parameters and one optional parameter:
paymentMethods
defines which forms of payment are accepted. For example, you may only accept Visa and MasterCard credit cards.paymentDetails
contains the total payment amount due, taxes, shipping cost, display items, etc.options
is an optional argument used to request additional details from the user, such as name, email, phone, etc.
Let's create a new payment request with only the required parameters:
const paymentMethods = [
{
supportedMethods: ['basic-card']
}
]
const paymentDetails = {
total: {
label: 'Total Amount',
amount: {
currency: 'USD',
value: 8.49
}
}
}
const paymentRequest = new PaymentRequest(paymentMethods, paymentDetails)
Notice the supportedMethods
parameter in paymentMethods
object. When it is set to basic-card
, both debit and credit cards of all networks will be accepted. However, we can limit the supported networks and types of cards. For example, with the following only Visa, MasterCard, and Discover credit cards are accepted:
const paymentMethods = [
{
supportedMethods: ['basic-card'],
data: {
supportedNetworks: ['visa', 'mastercard', 'discover'],
supportedTypes: ['credit']
}
}
]
// ...
Payment Details
The second parameter passed to the PaymentRequest
constructor is the payment details object. It contains the total of the order and an optional array of display items. The total
parameter must include a label
parameter and an amount
parameter with currency
and value
.
You can also add additional display items to provide a high-level breakdown of the total:
const paymentDetails = {
total: {
label: 'Total Amount',
amount: {
currency: 'USD',
value: 8.49
}
},
displayItems: [
{
label: '15% Discount',
amount: {
currency: 'USD',
value: -1.49
}
},
{
label: 'Tax',
amount: {
currency: 'USD',
value: 0.79
}
}
]
}
The displayItems
parameter is not meant to display a long list of items. Since space is limited for the browser's payment UI on mobile devices, you should use this to display only top-level fields such as subtotal, discount, tax, shipping cost, etc.
The
PaymentRequest
API does not perform any calculations. So, your web application is responsible for providing the pre-calculatedtotal
amount.
Requesting Additional Details
The third optional parameter can be used to request additional information from the user, such as name, email address, and phone number:
// ...
const options = {
requestPayerName: true,
requestPayerPhone: true,
requestPayerEmail: true
}
const paymentRequest = new PaymentRequest(paymentMethods, paymentDetails, options)
By default, all of these values are false
, but adding any of them to the options
object with a value true
will result in an extra step in the payment UI. If the user has already stored these details in the browser, they will be pre-populated.
Display Payment UI
After creating a PaymentRequest
object, you must call the show()
method to display the payment request UI to the user. The show()
method returns a promise that resolves with a PaymentResponse
object if the user has successfully filled in the details. If there is an error or the user closes the UI, the promise rejects.
// ...
const paymentRequest = new PaymentRequest(paymentMethods, paymentDetails, options)
paymentRequest
.show()
.then(paymentResponse => {
// close the payment UI
paymentResponse.complete().then(() => {
// TODO: call REST API to process the payment at the backend server
// with the data from 'paymentResponse'.
})
})
.catch(err => {
// user closed the UI or the API threw an error
console.log('Error:', err)
})
With the above code, the browser will show the payment UI to the user. Once the user has filled in the details and clicked on the 'Pay' button, you will receive a PaymentResponse
object in the show()
promise. The payment request UI is closed immediately when you call the PaymentResponse.complete()
method. This method returns a new promise so that you can call the backend server with the information collected and process the payment.
If you want to call the backend server to process the payment while the payment UI is showing a spinner, you can delay the call to complete()
. Let us create a mock function for payment processing with the backend server. It takes paymentResponse
as a parameter and returns a promise after 1.5 seconds that resolves to a JSON object:
const processPaymentWithServer = paymentResponse => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ status: true })
}, 1500)
})
}
//...
paymentRequest
.show()
.then(paymentResponse => {
processPaymentWithServer(paymentResponse).then(data => {
if (data.status) {
paymentResponse.complete('success')
} else {
paymentResponse.complete('fail')
}
})
})
.catch(err => {
console.log('Error:', err)
})
In the example above, the browser payment UI will show a processing screen until the promise returned by the processPaymentWithServer()
method is settled. We also used 'success' and 'fail' strings to tell the browser about the transaction outcome. The browser will show an error message to the user if you call complete('fail')
.
Payment Request Abort
If you want to cancel the payment request due to no activity or any other reason, you can use the PaymentRequest.abort()
method. It immediately closes the payment request UI and rejects the show()
promise.
// ...
setTimeout(() => {
paymentRequest
.abort()
.then(() => {
// aborted payment request
console.log('Payment request aborted due to no activity.')
})
.catch(err => {
// error while aborting
console.log('abort() Error: ', err)
})
}, 5000)
Conclusion
That's the end of a quick introduction to JavaScript Payment Request API. It provides a browser-based method to collect customer payment and contact information that can be sent to the backend server to process the payment.
The aim is to reduce the number of steps in completing an online payment. It makes the whole checkout process smoother by remembering the user's preferred way of paying for goods and services.
If you want to learn more about the Payment Request API, here is a good resource that discusses the main concepts and usage of the API.
Are you looking for other code tips?
JS Nooby
Javascript connoisseur