We develop mobile apps for parking payment. The key challenge is the session model: a parking session starts upon entry and ends upon exit or when purchased time expires. The user must know exactly how much time is left and receive a warning before penalties kick in. This requires precise push notifications, background timers, and reliable payment gateway integration.
Recently, we handled a case where a parking operator lost up to 15% of revenue (about 1.2 million rubles per year) due to unpaid extensions. Users forgot to extend, and push notifications didn't always arrive. We developed an app that solved this: added SMS duplication, improved the timer, and implemented automatic extension. Result: fines dropped by 95%, extension conversion rose by 40%. Savings for the operator: over 500,000 rubles in the first quarter.
Our experience: over 7 years in mobile development, dozens of implemented parking solutions. We guarantee the app passes App Store and Google Play moderation on the first attempt, including privacy requirements (ATT, Privacy Nutrition Labels) per App Store Review Guidelines Section 4.2.
Contact us to discuss your project and get a demo. Order a consultation to estimate the scope of work.
Apple Vision Framework documentation
How to organize session management in a parking payment app?
The central entity is ParkingSession. It has a lifecycle:
IDLE → ACTIVE → EXPIRING (15 min before end) → EXPIRED / EXTENDED State transitions are managed on the server. The app displays the current state via polling or WebSocket. The local timer is for UI only, not for business logic.
A typical session object:
{ "sessionId": "PSN-SESSION-4471", "zoneCode": "A-12", "vehiclePlate": "А123ВС77", "startedAt": "2024-07-15T10:15:00+03:00", "expiresAt": "2024-07-15T12:15:00+03:00", "rate": 60, "currency": "RUB", "status": "ACTIVE", "paymentStatus": "PAID" } Why is accurate session state synchronization important?
A mismatch between server time and local timer can cost the user a fine. Therefore, we use server time as the single source of truth. The local counter is only for display. Each time the app opens or receives a push, the session is re-fetched from the server. For critical notifications (5 minutes before expiration), we duplicate sending via FCM and SMS if push is undelivered (optional).
License plate recognition via camera — mobile app development
Manual plate entry is poor UX. Camera recognition is better. On iOS we use Vision + VNRecognizeTextRequest. On Android — ML Kit Text Recognition. Recognition accuracy for Russian plates on good images is around 85–90%. For tough cases, we use server-side OpenALPR.
import Vision func recognizePlate(from pixelBuffer: CVPixelBuffer) { let request = VNRecognizeTextRequest { [weak self] request, error in guard let observations = request.results as? [VNRecognizedTextObservation] else { return } let candidates = observations.compactMap { $0.topCandidates(1).first?.string } let plateRegex = /[АВЕКМНОРСТУХ]{1}\d{3}[АВЕКМНОРСТУХ]{2}\d{2,3}/ let plate = candidates.compactMap { $0.firstMatch(of: plateRegex)?.0 }.first DispatchQueue.main.async { self?.vehiclePlateField.text = plate.map(String.init) ?? "" } } request.recognitionLevel = .accurate request.recognitionLanguages = ["ru-RU"] let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer) try? handler.perform([request]) } How to ensure reliable push notification delivery in a parking payment app?
One common problem is push loss due to iOS power saving mode or Android Doze. We solve this through:
- high-priority FCM messages with a collapsing key to avoid notification duplication;
- SMS duplication for critical situations (optional);
- a local fallback timer that fires if no server response arrives 2 minutes before the deadline.
The countdown timer is the most requested UI element. On iOS it lives in ProgressView + Timer, on Android in CountDownTimer. But background notifications go through APNs/FCM.
Server-side notification logic:
- 15 minutes before expiresAt → push "Parking expires in 15 minutes"
- 5 minutes before → push with buttons "Extend by 1 hour" / "End"
- At expiresAt → push "Parking session ended"
On iOS, buttons in push notifications are implemented via UNNotificationCategory. Pressing "Extend" from the notification opens the app on the extension screen and automatically initiates payment with a saved card without extra steps.
How to integrate the app with a payment gateway?
Parking payment has two scenarios:
Pre-paid — buy time before entry. User selects zone, time, pays. Server issues a session code. At entry, an operator scans a QR or reads the plate.
Post-paid — pay at exit. Session starts automatically upon entry (by plate), amount calculated at exit, app prompts payment.
Comparison:
| Criteria | Pre-paid | Post-paid |
|---|---|---|
| Payment time | Before entry | At exit |
| Underpayment risk | Minimal | Possible if payment delay |
| Required infrastructure | Barrier/operator for verification | Automatic plate capture |
| UX | User must guess time | Pay after, more convenient |
For both scenarios, we use a saved card via a provider token (CloudPayments, YooKassa, Stripe). One-time payment without saving card: via a payment web widget in WKWebView/WebView. Regular payments (subscription): via recurring payments with a token.
Integration with parking equipment
If the parking lot uses an access control system or barrier, integration is through the operator's server API. Common protocols: SOAP/XML (legacy), REST JSON (modern). The app does not talk to equipment directly — only via the backend.
For barrier opening via QR code at exit, we use AVCaptureSession.
Detailed technical scheme
| Component | iOS | Android |
|---|---|---|
| UI | SwiftUI + UIKit (camera) | Jetpack Compose + CameraX |
| Plate recognition | Vision Framework | ML Kit Text Recognition |
| Maps | MapKit / Google Maps SDK | Google Maps SDK |
| Payments | Stripe iOS SDK / CloudPayments | Stripe Android SDK / CloudPayments |
| Push | APNs via Firebase | FCM |
| Architecture | MVVM + Combine | MVVM + StateFlow |
What's included in the development?
We deliver a complete package:
- Architectural documentation (diagrams, API description)
- Source code with unit test coverage (>70%)
- CI/CD setup (GitHub Actions, GitLab CI)
- Integration with payment gateway and parking API
- Publication to App Store and Google Play (including screenshots, descriptions)
- Admin and user manuals
- Technical support for 2 weeks after release
- Access to repository and task management system
- Training for the operator's team on the admin panel
How does the development process work?
We follow these stages:
- Requirements analysis and prototyping (3 days)
- Architecture and API design
- MVP development with core features
- Integration with payment gateway and parking API
- Testing (unit >70%, integration, UI)
- Publication to App Store and Google Play
Base version (sessions, timer, card payment, push): 4 to 6 weeks. Adding plate recognition, equipment integration, subscriptions: another 2 to 4 weeks. Cost is calculated individually after requirements analysis.
Contact us to discuss your project — we'll prepare a prototype in 3 days and propose an optimal solution. A separate consultation on architecture and integrations is also available. Order development and get a finished app on time.







