How to Connect a POS Terminal to a Mobile App?
Connecting a mobile app to a POS terminal is not just "send the amount to the terminal". It's integration with proprietary hardware protocols—each manufacturer has their own—plus handling all possible communication failures during a financial transaction. Our company has 7+ years of experience in mobile development and has implemented over 20 integrations with POS terminals for various acquirers. Our approach covers all edge cases to ensure every transaction completes correctly.
Typical scenario: a cashier in a supermarket processes a payment via a mobile app, the terminal authorizes the card, but the connection drops. What to do? Our solution includes an automatic status request for the last transaction and a reconnection mechanism with 5 attempts, achieving a 99% success rate in determining the status. Order a turnkey integration—we handle all stages: from protocol analysis to testing on real hardware. We'll evaluate your project within two business days.
Protocols and Manufacturers
Most POS terminals in retail communicate via one of the standard interface protocols:
- ECR protocol (Electronic Cash Register) — a set of commands to send the amount from the cash register app to the terminal. Each bank-acquirer or manufacturer has its own implementation: Sberbank (SBOL), VTB, Ingenico, Verifone—all differ in command syntax and response fields.
- OPI (Open Payment Initiative) / OPOS (OLE for POS) — more standardized protocols, popular in Europe.
- Proprietary SDKs: PAX A-series, Sunmi V2, Newland—have their own Android SDKs (the terminal itself runs Android, we call AIDL interfaces or Intents).
Before starting development, we clarify with the client: which specific terminal, which bank-acquirer, which protocol is supported. This is not a developer's technical choice—it's a fact about the installed equipment.
| Protocol | Manufacturers | Complexity | Speed | Standardization |
|---|---|---|---|---|
| ECR | Sberbank, VTB, Alfa-Bank | Medium | High | None, own implementation |
| OPI/OPOS | Ingenico, Verifone | High | Medium | Yes |
| Proprietary SDK | PAX, Sunmi, Newland | Low | High | No |
What Interfaces Are Used?
Bluetooth (BLE + Classic). The terminal acts as a GATT server (BLE) or classic Bluetooth serial device. On iOS: CoreBluetooth for BLE; classic Bluetooth only through the ExternalAccessory framework with MFi certification. This is an important limitation: most POS terminals use the classic Bluetooth SPP profile, and without MFi certification from the terminal manufacturer, iOS cannot connect via classic BT. Android has no restrictions—BluetoothSocket + RFCOMM.
USB. Android: UsbManager, UsbDeviceConnection. iOS: Lightning/USB-C accessory—again requires MFi. In practice, USB connections are rarer than Bluetooth.
TCP/IP (Wi-Fi / LAN). The terminal is on the local network; the app connects via IP:Port and sends commands in text or binary format. URLSession / OkHttp for HTTP commands or CFStream / Java Socket for raw TCP. The most predictable interface from iOS's perspective.
Payment Flow
- The app forms a "sale" command with the amount and additional parameters.
- Sends it to the terminal.
- The terminal shows the payment screen to the user and accepts the card.
- Returns a response: status (
approved/declined/error), authorization code, RRN, masked PAN. - The app processes the response and continues the business flow (closes the receipt, updates the order).
Steps 2–4 may take up to 60–90 seconds with slow payment processing. During this time, we show a spinner with the message "Waiting for terminal response" and a "Cancel" button (which sends a cancel command to the terminal, not just closes the screen).
What to Do When Connection Drops During a Transaction?
The most unpleasant case: the transaction was sent to the terminal, connection was lost—the app doesn't know whether the payment went through. The terminal authorized the card, but the response didn't arrive.
The correct approach: upon connection loss—attempt to get the status of the last transaction ("last operation request" command). If the terminal responds, we take the status from there. If not, we show the operator "Status unknown, check the terminal" and save the transaction in PENDING status. Automatic charge when status is unknown is unacceptable.
Reconnect logic: on Bluetooth disconnection—automatic reconnection with 5 attempts, exponential backoff. Connection status is always visible in the UI (status icon).
Void and Refund
Void (reversal) — before the financial day closes. Refund — after. Both require separate commands to the terminal with the RRN of the original transaction. We implement both scenarios so the operator can correct errors.
Platform Comparison: Android vs iOS
| Aspect | Android | iOS |
|---|---|---|
| Classic BT (SPP) | Natively, BluetoothSocket |
Only MFi devices |
| BLE | BluetoothGatt |
CoreBluetooth |
| USB | UsbManager |
Only MFi |
| TCP/IP | Socket / OkHttp |
CFStream / URLSession |
If the client requires iOS and the terminal only works with classic Bluetooth without MFi, the only path is TCP/IP through an intermediate adapter or switching to a terminal with BLE/TCP support.
By the way, the BLE protocol typically provides lower latency (up to 50 ms) compared to classic Bluetooth (100–200 ms), speeding up the transaction by 2–4 times. This is important for high-throughput scenarios. More details in Apple's CoreBluetooth documentation.
Common Integration Mistakes
- Not accounting for MFi certification on iOS for classic Bluetooth—results in connection impossibility.
- Lack of retry logic on disconnection—lost transactions.
- Using the wrong protocol (e.g., ECR for a terminal that only supports OPI).
- Incorrect parsing of the terminal response (different error codes from different manufacturers).
What's Included in the Work
- Analysis of equipment and acquirer protocols.
- Implementation of the transport layer (Bluetooth/USB/TCP).
- Development of command protocol (sale, void, refund, status request).
- Handling edge cases (connection drop, timeout, unknown status).
- Testing on a real terminal in the acquirer's test mode.
- Integration documentation for client support.
- Warranty on the transport layer: 6 months free support.
The integration cost is fixed at the specification stage, and the return on investment is achieved through automation of manual data entry. Get a consultation for your project—we'll assess the complexity and timeline.
Process
Determine terminal model and protocol → study acquirer documentation → implement transport layer (BT/USB/TCP) → command protocol (sale, void, refund, status request) → handle edge cases (connection drop, timeout) → test on real terminal in acquirer test mode → production testing → deployment.
Timeline Estimates
Basic integration (sale + response) over a single protocol with one interface: 3–5 days. Full set of operations (sale, void, refund, status request) with retry/reconnect logic and multiple interfaces: 2–3 weeks.
Our team consists of mobile developers with 7+ years of experience in iOS (Swift, SwiftUI, CoreBluetooth) and Android (Kotlin, Jetpack Compose, BluetoothSocket). We have worked with terminals from PAX, Ingenico, Verifone, Sunmi. We guarantee integration quality and transparency at every stage.
Order a POS terminal integration—and we'll ensure stable operation of the payment module in your app.







