POS Terminal Connection Implementation in Mobile App
Connecting a mobile app to a POS terminal isn't simply "send amount to terminal." It's integration with proprietary hardware protocols—each manufacturer has their own—plus handling every possible communication failure during a financial operation.
Protocols and Manufacturers
Most retail POS terminals communicate via one of the standard interface protocols:
ECR Protocol (Electronic Cash Register) — set of commands to pass amount from cash app to terminal. Each bank-acquirer or manufacturer implements differently. Sberbank (SBOL), VTB, Ingenico, Verifone—all have different command syntax and response fields.
OPI (Open Payment Initiative) / OPOS (OLE for POS) — more standardized, popular in Europe.
Proprietary SDK: PAX A-series, Sunmi V2, Newland have their own Android SDKs (the terminal itself runs Android, invoke AIDL interface or Intent).
Before development, confirm with the client: which specific terminal, which bank-acquirer, which protocol. This isn't a developer choice—it's hardware fact.
Connection Interfaces
Bluetooth (BLE + Classic). Terminal is a GATT server (BLE) or classic Bluetooth serial device. iOS: CoreBluetooth for BLE; classic Bluetooth only via ExternalAccessory framework with MFi certification. Important: most POS terminals use classic Bluetooth SPP profile, and iOS without MFi certification from the terminal manufacturer can't connect via classic BT. Android has no restrictions—BluetoothSocket + RFCOMM.
USB. Android: UsbManager, UsbDeviceConnection. iOS: Lightning/USB-C accessory—again, MFi required. USB is rarer than Bluetooth in practice.
TCP/IP (Wi-Fi/LAN). Terminal on local network, app connects by IP:Port, sends commands in text or binary. URLSession / OkHttp for HTTP or CFStream / Java Socket for raw TCP. Most predictable for iOS.
Payment Operation Flow
- App formats "sale" command with amount and extra params.
- Sends to terminal.
- Terminal shows payment screen to user, accepts card.
- Returns response: status (
approved/declined/error), auth code, RRN, masked PAN. - App processes and continues (close receipt, update order).
Steps 2–4 can take 60–90 seconds with slow acquiring. Show spinner "Waiting for terminal response" and a "Cancel" button (sends cancel command to terminal, not just closes screen).
Error Handling
Worst case: transaction sent, connection lost—the app doesn't know if payment succeeded or not. Terminal authorized the card but response didn't arrive.
Correct approach: on connection loss, try getting the last transaction status (command "query last operation"). If terminal responds, take the status. If not, show operator "Status unknown, check terminal" and save transaction as PENDING. Never auto-debit on unknown status.
Reconnect logic: Bluetooth drop → auto-reconnect with 3–5 attempts, exponential backoff. Connection state always visible in UI (icon).
Reversal and Refund
Reversal (cancellation)—before close of business day. Refund—after. Both require separate commands to terminal with RRN from original transaction. Support both—operator must correct mistakes.
Android vs iOS
| Aspect | Android | iOS |
|---|---|---|
| Classic BT (SPP) | Native, BluetoothSocket |
MFi devices only |
| BLE | BluetoothGatt |
CoreBluetooth |
| USB | UsbManager |
MFi only |
| TCP/IP | Socket / OkHttp |
CFStream / URLSession |
If the client requires iOS and the terminal only works via classic Bluetooth without MFi, the only path: TCP/IP via intermediate adapter or switch to a terminal with BLE/TCP support.
Process
Determine terminal model and protocol → study acquirer docs → implement transport layer (BT/USB/TCP) → command protocol (sale, reversal, refund, query status) → edge-case handling (connection loss, timeout) → test on real terminal in acquirer test mode → live testing → deployment.
Timeline Estimates
Basic integration (sale + response) for a specific protocol, one interface: 3–5 days. Full operation set (sale, reversal, refund, status query) + retry/reconnect + multiple interfaces: 2–3 weeks.







