Kasa uygulamamız, sağlayıcının cihazdaki uygulamasını iki yoldan çağırabilir: aynı cihazdaysa Android Intent, ayrı cihazdaysa HTTP. Taşıma değişse de mesaj şekli AYNIDIR — tek bir nexo mesaj modeli öğrenirsiniz. Bulut tarafınız (tutar çekme, sonuç bildirme, cihaz kaydı) hiç değişmez.
⚠️ PRODUCTION'a HENÜZ DAĞITILMADI — yalnız dev ortamında.
⏳ Android Intent'in ALAN ADLARI (action, extra anahtarları) henüz yayınlanmadı. Bu sayfa modeli ve kararları anlatıyor; somut Intent sözleşmesi ölçülüp yakalandığında eklenecek. Şimdiden mimarinizi kurabilirsiniz — alan adlarına kod yazmayın.
İki senaryo, tek mesaj
Aynı cihazda (kasa tableti + sağlayıcı uygulaması) → Intent (uygulama çağrısı)
Ayrı cihazda (kasa + ağdaki terminal/PC) → HTTP
Her iki durumda da MESAJ AYNI:
gidiş : nexo SaleToPOIRequest
dönüş : nexo SaleToPOIResponse
İKİ AYRI ENTEGRASYON YAZMAYIN. Masaüstünde HTTP gövdesi olarak giden SaleToPOIRequest, Android'de Intent içinde bir metin alanı olarak gider. Yanıt da aynı SaleToPOIResponse'tur. Yani tek mesaj modeli, iki taşıma. Ayrı sözleşme yoktur; ayrı yazarsanız gereksiz iş yapar ve iki kod yolunu ıraksatırsınız.
Model: üç bağımsız parça
Bizim kasa uygulamamız — tek bir uygulama, hiçbir markayı tanımaz.
Sizin uygulamanız — her marka kendi uygulamasını yazar.
Fiziksel terminal — sizin işiniz (Bluetooth/USB/ağ); platformu ilgilendirmez.
Hepsi-bir-arada bir terminal hedeflenmiyor: parçalar bağımsız değişebilsin diye ayrıldı.
Android: sunucu değil, tek ekran
Android'de yazacağınız şey tek bir ekrandır (Activity): bizim JSON'umuzu alır, kartı okutur, bizim JSON'umuzu döndürür. Sunucu yazmazsınız.
Neden HTTP değil — karar operasyonel maliyetten çıktı: HTTP olsaydı uygulamanız sürekli açık bir sunucu tutmak zorunda kalırdı. Android'de bu, kalıcı bildirim gösteren bir ön plan servisi demektir: kullanıcı görür, kapatmaya çalışır, sistem yine de düşürebilir — ve her sağlayıcı bunu ayrı ayrı doğru yapmak zorunda kalırdı.
Intent'te uygulamanız hiç arka planda çalışmaz: sistem onu ödeme anında başlatır, kart okunur, sonuç döner. Sunucu yok, port yok, bildirim yok, yeniden bağlanma yönetimi yok. Bu bir sapma da değildir — nexo, taşıma seçeneklerini sayarken "cihaz içindeyse Intent" der.
Android manifest gereksinimleri — ikisi de ZORUNLU
Bu iki kural ölçüldü ve alan adlarından bağımsızdır — Intent sözleşmesi yayınlanmadan da uygulayabilirsiniz.
<!-- Ödeme activity'nizin AndroidManifest.xml tanımı -->
<activity
android:name=".OdemeActivity"
android:exported="true" <!-- Android 12+ ZORUNLU -->
android:launchMode="standard"> <!-- veya singleTop; BAŞKASI YASAK -->
<intent-filter>
<action android:name="…" /> <!-- ⏳ adı henüz yayınlanmadı -->
<category android:name="android.intent.category.DEFAULT" /> <!-- ZORUNLU -->
</intent-filter>
</activity>
1. android.intent.category.DEFAULT ZORUNLU (+ android:exported="true", Android 12+ için).
Yoksa uygulama kurulu olduğu hâlde eşleşme olmaz ve kasa kasiyere "ödeme uygulaması kurulu değil" der. Teşhis tamamen yanlış yöne gider: kurulumu, sürümü, cihazı kontrol edersiniz — oysa sorun manifest'teki tek satırdır.
2. launchModestandard veya singleTop olmalı.singleTask, singleInstance ve kendi taskAffinity'niz YASAK.
Sebebi ağır: activity farklı bir task'ta açılırsa sonuç, kart daha çekilmeden "iptal" olarak döner. Kasiyer iptal gördüğü için yeniden dener → çift tahsilat riski. Bu, kodunuz doğru olsa bile yalnız manifest yüzünden oluşur.
⚠️ Güvenlik: çağrı AÇIK HEDEFLİ yapılır
Uygulamanız paket adıyla hedeflenerek çağrılır — "kim ödeme yapabiliyorsa o alsın" biçiminde DEĞİL.
Sebebi somut bir saldırı: örtük çağrıda kötü niyetli bir uygulama aynı tanımı kendine ekleyip daha yüksek öncelikle araya girebilir ve ödeme isteğini — kart verisiyle birlikte — kendisi karşılar. Android'in kendi güvenlik dokümanında bu, implicit intent hijacking başlığıyla ve kart verisinin çalındığı örnekle anlatılıyor.
Paket adınız terminal kaydında tutulur; çağrı ona göre hedeflenir. Yani kaydınızdaki paket adı doğru değilse çağrı size hiç ulaşmaz — bu bir hata değil, korumanın kendisidir.
ℹ️ Bunu SİZ beyan etmiyorsunuz. Paket adı, terminal kurulumu sırasında işletme yöneticisi tarafından girilir — eklenti manifest'inde böyle bir alan yoktur, aramayın. Teknik olarak terminal kaydının adres alanına android-app://paket.adiniz biçiminde yazılır; masaüstünde aynı alan http://127.0.0.1:PORT/… taşır. Taşımayı bu adres belirler, ayrı bir ayar yok.
Pratik sonucu: kuruluma giderken paket adınızı işletmeye bildirin; yanlış girilirse belirtisi "uygulama hiç çağrılmıyor" olur.