Did you know that you can accept in-person payments with Stripe? In this series, we’re going to dive headfirst into building an in-person payments integration using Stripe Terminal.
In our last post, we gave our web-based point-of-sale application the ability to authorize and capture in-person payments using Stripe’s payments and Terminal APIs.
In this blog post, we’re going to learn how to cancel payments after they’ve been sent to the reader, so that our application can accommodate any changes to the purchase amount.
New to this series? Be sure to check out our first post on how to set up a card reader for testing and development, our second post on connecting them to a web application, and our third post on authorizing and capturing in-person payments.
If you’ve been following along with the series, you‘ve learned how to:
- Register real or simulated card readers
- List online readers
- Test collecting in-person payments on physical and simulated readers.
In this blog post, we’ll learn how to cancel in-flight payments by resetting the reader to its idle state.
A payment is “in-flight” after the reader has been prompted to collect payment, but before the customer has tapped their card. At this point, you may need to cancel the payment for any number of reasons. Maybe the cashier has scanned the item too many times. Or perhaps the customer has simply decided to change their order at the last minute. Whatever the reason, the final amount has changed and your payment and reader needs to reflect the new amount.
Let’s build a backend endpoint for canceling a reader action. This route will allow us to reset the reader to its idle state. We can use it to cancel all kinds of reader actions. In this post, we’ll focus on canceling a reader action to process a payment, but just know that you could also use this endpoint to cancel other reader actions, like displaying the cart details on the reader.
On the backend in
server/server.js, we’ll create a
POST route for canceling a reader action. This route will expect a request body with a
reader_id, which represents the specific reader that we want to reset.
/cancel-reader-action endpoint will return a
reader object, which includes the state of the reader. We can inspect the reader’s
action property, which shows the reader’s most recent action. If we take a look at the action property, we see that it’s
null. This confirms that the reader has been reset successfully.
On the frontend in
client/reader.js, we’ll add an event listener to our Cancel button. If we get an error, we’ll log it to
#messages. Otherwise, we’ll redirect to the cancel page, where we can restart our payment.
Congratulations! If you’ve been following along, you should now have a complete in-person payments integration that’s able to collect and cancel in-person payments on a physical or simulated WisePOS E reader. 🎉
💡You can also see the completed project on Repl.it.
Your point-of-sales application is complete but, there are still a variety of features that you can add to improve the overall experience. Check out the Stripe docs to learn how to display the cart on the reader, accept tips, and save cards without charging them. We read these as exercises for the reader (for now 😉).
Want to stay up to date on Stripe’s latest integrations, features, and open-source projects?
Charles Watkins is a Developer Advocate at Stripe where he writes, codes, and livestreams about online payments. In his spare time, he enjoys drawing, gaming, and rewatching the first five seasons of Game of Thrones.