There are few things more integral to running a successful business when creating software than transacting money: it's a big deal!
So when we originally launched the OnTrac Point of Sale System for KARM Thrift Stores and other thrift stores throughout the US, we knew we would be circling back around to adding integrated payments via Heartland Payments soon!
Payment Processing Options
We typically advocate for using Stripe when integrating payment processing for mobile or web applications; it's streamlined, competitively priced, and very powerful allowing us to build a robust and full featured platform in less time.
However, until very recently Stripe hasn't offered any first-class physical payment processing solutions, such as what we needed to process credit and gift cards in stores connected to our iOS app. With an established relationship with Heartland Payments already in place at KARM Thrift Stores, the decision to integrate using their network and hardware offerings was simple for our client.
It's all about the Hardware
Heartland Payments is a payment processor, but not a hardware manufacturer. Therefore, they had a list of supported units from manufactures that we could use in our integration, and an SDK for communicating with those approved hardware units.
Our experience integrating their Objective-C SDK into our Swift iOS app was not the most pleasant from a developer perspective. The SDK is large, inconsistent, pieces are very poorly written and we encountered several bugs that took a lot of time to troubleshoot with the Heartland integration team via email.
Read more on how we offered integrated payments for OnTrac
Low level integration
As part of our integration, we were informed that the connection between our iOS app and the hardware terminal itself was sometimes expected to fail. I could repeat for importance.
This meant that the SDK we were using to send a command to the hardware card terminal, would sometimes just not execute a callback to our main application and we'd be lost waiting on a response from the terminal that would never come.
The recommended solution was to create a mechanism where we would request the details of the most recently completed transaction from the card terminal, after a certain timeout and having not received a response from the card terminal. The Heartland SDK didn't implement this functionality, so we had to enter into a Non-Disclosure Agreement to be a 3rd party vendor and gain access to the low-level spec for communicating with the card terminal itself.
Armed with a several hundred page low-level spec communication document, we set about adding functionality to communicate and request this needed information from the card terminal directly simple to see if the most recent transaction completed was indeed the one we wanted the card terminal to process, and therefore deal with the fact that we never received a callback from the card terminal, even though the transaction went through and the customer and cashier both thought everything worked well.
The solution looks seamless, but cost us a large amount of time debugging, reviewing documentation, troubleshooting the Heartland SDK, writing low-level socket connections in a custom protocol, and so much more.
Well worth the effort
Even though the integration was a painful process with many unexpected hiccups due to poor documentation, a poor SDK, lots of bureaucratic tape and overall a complex system of parts, it has been worth the effort in every way.
Our cashiers simply tap a payment method to capture an electronic payment, never leaving our POS app. Customers run their cards on the card terminal themselves which they love. We have less errors, avoid the hefty reconciliation process at the end of the day, have real time transaction info, and all of our systems are integrated with our payment provider so we gain insight into more operations data.
At the end of the day, we're delighted to have made our cashier's role simpler, less error prone, and more enjoyable so they can focus on providing the best customer experience for guests.