Ces points ont tous coûté plusieurs heures sur le premier site. Ils ne dépendent pas du lieu : ils se reproduiront sur n'importe quel déploiement du modèle.
Les URL des ressources doivent être absolues. Le
hotspot sert login.html sous le nom d'hôte demandé par le
client. Un Android qui teste sa connectivité demande
connectivitycheck.gstatic.com ; la page est alors servie
sous ce nom, et un href="style.css" relatif part chercher
la feuille de style chez Google. Résultat : une page brute, sans mise en
forme, réduite au titre. D'où, dans toutes les pages :
<link rel="stylesheet" href="http://<ip-routeur>/style.css">
<script src="http://<ip-routeur>/i18n.js"></script>
Ne pas mettre d'entrée DNS statique joker
(regexp=".*") pour forcer la redirection : elle capture
aussi les domaines de détection de portail captif et empêche le
téléphone d'ouvrir la bulle de connexion.
HTTPS ne redirige pas. Taper une adresse
https:// n'ouvre jamais le portail : c'est le comportement
normal d'un portail captif. La bulle de détection du système est le
chemin d'entrée.
Une radio = un canal. Si le routeur prend son Internet en WiFi (mode station) sur la même radio que le point d'accès, l'AP est verrouillé sur le canal du réseau amont. Si l'amont change de canal, la station décroche jusqu'à réalignement :
/interface wifi scan wifi-amont duration=8
/interface wifi set wifi1 channel.frequency=<canal relevé>
La radio partage en outre son temps entre les deux rôles : le débit
servi aux clients en souffre. Une arrivée Internet sur
ether1 reste préférable en exploitation.
RouterOS refuse le mot de passe dès qu'une clé est
importée pour l'utilisateur, tant que
always-allow-password-login vaut no (la valeur
par défaut). Symptôme côté application :
Auth fail for methods 'publickey,password'. Correctif :
/ip ssh set always-allow-password-login=yes
Les clés Ed25519 sont inutilisables sur Android avec
JSch. Les implémentations Ed25519 de
com.github.mwiede:jsch vivent dans
META-INF/versions/15/ — un JAR multi-release, que le
compilateur D8/R8 d'Android ignore. Sur Android ces classes n'existent
tout simplement pas, et charger la clé fait échouer toute la phase
d'authentification avant même le repli sur mot de passe. La caisse
Android s'authentifie donc par mot de passe, et l'APK
contient ce mot de passe : ne pas le diffuser hors du personnel de
caisse.
Ordre des opérations sur un canal JSch : obtenir les
flux avant connect(), les lire après.
Lire avant connect() bloque indéfiniment —
readText() attend un EOF qui ne viendra jamais sur un canal
non ouvert. Avec un exécuteur à un seul fil, toutes les ventes suivantes
restent en file et l'application paraît figée.
Toujours lier le bypass à l'adresse MAC, jamais à l'IP : le bail DHCP change et le bypass tombe.
Désactiver la randomisation d'adresse MAC d'Android
pour ce SSID sur les téléphones de caisse (Paramètres WiFi → réseau →
Confidentialité → utiliser le MAC de l'appareil). Sinon l'adresse change
et le bypass ne correspond plus : la caisse ne joint plus le routeur et
échoue sur un Timeout/ConnectException.
Sans bypass, le téléphone de caisse est intercepté par le portail et ne peut pas ouvrir de session SSH vers le routeur.
Les points d'accès supplémentaires doivent être en mode pont, jamais en NAT. Derrière un NAT, tous leurs clients apparaissent au hotspot comme un seul appareil : un unique voucher couvrirait tout le monde.
Le compte caisse n'a pas la politique ftp :
il ne peut ni téléverser les pages du portail, ni faire
/system backup save, ni /export. Ces
opérations passent par le compte admin.
L'API de la caisse web écoute sur 0.0.0.0:8080 et
n'oppose qu'un PIN à 4 chiffres, sans limitation du nombre de tentatives
: tout appareil du réseau peut l'énumérer et émettre des vouchers. À
restreindre (pare-feu, écoute sur 127.0.0.1, PIN plus long)
si le PC de caisse est joignable par les clients.
Modèle SATELLITE — documentation générique. Les identifiants réels ne figurent pas dans ces pages.