Note app mobile : alignement manuel et stock avant « Prêt à vendre » (routeur sans VPN)
Date : 2026-10-10 · Destinataire : dev app mobile (MV7) · API : https://live.jmoai.net
1. Le cas
Quand le vendeur n’a pas de VPN actif (mode APP_BRIDGE, sans tunnel), le serveur ne peut jamais
joindre le routeur. Deux conséquences :
- L’alignement du NAS doit être fait et prouvé par l’app, qui est sur le même réseau que le routeur.
- La vente puise uniquement dans le stock envoyé par l’app. Sans tunnel, le serveur ne peut pas créer un ticket à la volée. Stock vide = vente payée sans ticket.
L’app doit donc garantir les deux, avant que la boutique passe au vert.
2. Le parcours attendu
1. Vérifier l'alignement sur le routeur (app, en local)
2. Déclarer le NAS POST /api/v1/clients/tiketmomo/nas-declaration
3. Lire la réponse du backend ALIGNED / RECONCILED → continuer ; REFUSED → corriger
4. Générer le stock des forfaits (app, sur le routeur)
5. Envoyer le stock POST /api/v1/clients/vouchers/sync
6. Relire l'état GET /api/v1/clients/store/points/<point_id>
7. Afficher « ✅ Prêt à vendre » UNIQUEMENT si ready_to_sell === true
3. Étape 1 : ce que l’app vérifie sur le routeur
L’alignement est conforme seulement si tout ceci est vrai :
- Un seul serveur hotspot actif. S’il y en a plusieurs, le vendeur doit choisir lequel vend : le backend refusera de deviner.
- Le nom du serveur hotspot est l’identifiant NAS attribué à cette boutique, par exemple
TM-1279(ou un nom qui se termine par-TM1279). C’est ce nom que le routeur insère dans les liens de paiement via$(server-name). - Le numéro de série du routeur est lu sur le routeur lui-même (
/system routerboard). Ne le demandez jamais au vendeur. - Les forfaits commerciaux existent sur le routeur, avec un nom au format
<prix>F-<durée>ou<prix>F-<data>(100F-2h,500F-3d,100F-1GB). Les profils sans chiffres (default,VIP…) ne sont pas commerciaux et sont ignorés.
Si un point échoue, affichez ce qu’il faut corriger. N’envoyez la déclaration qu’une fois l’alignement conforme.
4. Étapes 2 et 3 : déclarer et lire la réponse
POST /api/v1/clients/tiketmomo/nas-declaration. Le contrat existant reste valable : il porte le
router_serial, les hotspot_servers, et les faits du routeur (modèle, version, identité, DNS,
adresse locale).
| Réponse | Sens | Action de l’app |
|---|---|---|
200 ALIGNED |
le backend et le routeur concordent | passer à l’étape 4 |
200 RECONCILED |
le backend s’est aligné sur le routeur | passer à l’étape 4 |
200 REFUSED + ROUTER_BOUND_ELSEWHERE |
ce routeur est rattaché à une autre boutique (bound_store_slug) |
afficher le nom de cette boutique ; ne pas continuer |
200 REFUSED + ROUTER_NOT_OWNED |
le routeur appartient à un autre compte | « Contactez le support » |
200 REFUSED + ROUTER_UNKNOWN |
numéro de série inconnu, ou différent de l’équipement enregistré (expected_serial) |
vérifier le routeur ; ne pas continuer |
Une déclaration acceptée ne suffit pas pour vendre : le stock manque encore.
5. Étapes 4 et 5 : le stock
- Générez des tickets sur le routeur, pour chaque forfait commercial qui sera proposé à la vente.
- Règle du propriétaire : au moins 3 forfaits commerciaux doivent avoir du stock pour que la boutique passe en « Prêt à vendre ». Quantité recommandée : 30 tickets par forfait, au minimum 5.
- Envoyez-les :
POST /api/v1/clients/vouchers/sync, avecmetadata.routerSerial(le numéro de série lu à l’étape 1). C’est obligatoire, voir le mémo « vouchers/sync v2 par NAS ».- Sans numéro de série ni NAS sur un compte à plusieurs routeurs →
400 NAS_REQUIRED. - Routeur inconnu ou d’un autre compte →
404 ALLOCATION_NOT_FOUND.
- Sans numéro de série ni NAS sur un compte à plusieurs routeurs →
- ⚠️ Taille des envois : la route accepte désormais des corps jusqu’à 5 Mo pour éviter le
413constaté le 08/10.- Envoyez par lots de 100 tickets au plus, en enchaînant les appels.
- Le backend refuse tout de même les lots de plus de 2 000 tickets avec
400 BATCH_TOO_LARGE.
- Un forfait sans stock ne doit pas être proposé dans le portail captif tant qu’il n’a pas de tickets. Un acheteur qui le paierait ne recevrait rien.
6. Étapes 6 et 7 : « Prêt à vendre »
GET /api/v1/clients/store/points/<point_id> renvoie ready_to_sell et readiness (contrat détaillé :
CONTRAT-API-PRET-A-VENDRE, publié à la livraison backend).
ready_to_sell === true→ « ✅ Prêt à vendre ». Il garantit :- NAS aligné, licence valide, routeur vu récemment ;
- au moins 3 forfaits commerciaux en stock ;
- encaissement en ordre.
false→ affichez chaque élément dereadiness.blocking[](code+detailen français), avec l’action correspondante (« Générez du stock pour 200F-12h », etc.).alignment.status:NO_ROUTER,NAS_NOT_ALIGNED,NEEDS_ATTENTION(aligné mais pas prêt) ouALIGNED(prêt).- Le résultat peut avoir jusqu’à 60 secondes de retard. Après un envoi de stock, attendez quelques secondes, puis relisez.
- Ne calculez jamais « prêt » dans l’app. Affichez seulement ce que renvoie le backend.
7. Recette
- Routeur sans VPN, deux serveurs hotspot → l’app demande de choisir avant de déclarer.
- Nom du serveur hotspot différent du NAS → l’app bloque et explique.
- Déclaration acceptée sans stock →
ready_to_sell=false, avec un blocage de stock. - Stock sur 2 forfaits seulement → toujours
false. - Stock sur 3 forfaits →
true: « ✅ Prêt à vendre ». - Un envoi de 300 tickets découpé en 3 lots → aucun 413.
Questions et écarts : les remonter avec l’heure, la route appelée et le corps de la réponse.