A freelancing client asked me to build a website for their local roller rink. They wanted all billing – both in-store and online – to be consolidated under one platform, so naturally I thought of Square. Square has a great in-store POS, but also supports online transactions in WooCommerce. But there was one challenge that I found interesting: how to build a check-in kiosk in WordPress with payments accepted via a Square terminal.
While Square does have a WooCommerce plugin to take payments, this is handled entirely via manual credit card input. The fee structure is higher than for “card present” transactions, and obviously customers entering the rink wouldn’t want to manually type their credit card number anyway. In the past I’ve gotten around this by using a magstripe reader. These are cheap (>$20) and act as a pseudo-keyboard, “typing” the data they read off of a card’s magstripe. This works, but these days many card processors are treating magstripe reads as card not present due to how easy they are to store and replay. Chip and tap payments are here to stay and very much preferred due to being much more secure.
So that brings us back to the Square terminal. The Square terminal connects to a Square account and can take chip and tap transactions, while also supporting swipe if no other options are available. It can also read Square gift cards, which was handy since my client wanted to offer gift cards. But out of the box, it is meant for manual operation, that is, the store owner enters the transaction, presents the terminal to the customer for payment, then takes it back afterwards. These kiosks were meant to be unattended, so the usual mode wouldn’t work.
However, the terminals can operate in an alternate mode where they “listen” for a transaction request, take the payment, then return to the waiting mode. It’s a fairly complex setup, but this is the sort of thing that gets my creative juices flowing 🙂 After researching the APIs and going through some testing and trial and error, I was able to build out a flow that works pretty well. Here’s how it works.
Initial setup
The setup process for this flow is itself non-trivial. It starts with an API call to Square to tell it you want to connect a device. This call is simple – it just requires the Square account key and the location ID to link the terminal to. It returns a device code request ID, a login code, and a status of “unpaired”. The person setting up the terminal then enters the login code into the terminal, and the terminal completes the login and goes into the aforementioned “listening for payment requests” mode. My code checks for this by pinging the Square API using the device code request ID; once pairing is complete the device code request switches from “unpaired” to “paired”. Crucially, the response for a paired terminal will now include a device ID. The device ID is what’s used to make future payment requests, and is stored in the kiosk.
Taking a payment
With the terminal now paired and the device ID in hand, the kiosks could take payments. The flow for this is as follows:
- The kiosk determines the amount to charge, and sends a request to Square with the device ID and amount.
- Square returns a payment request ID (which is stored in a custom table) and sends the signal to the terminal to take a payment.
- The terminal activates, requesting payment.
- The customer completes the payment.
- The terminal tells Square’s servers that the payment has been received.
- Square’s servers send a webhook to my client’s server hosting the kiosks to confirm payment complete.
- My client’s server updates the row of the custom table to indicate the completed status.
- The kiosk queries the server every few seconds to check if the payment is complete.
- When the kiosk sees that the payment is complete, it prints wristbands.