Mode démo : une boutique de référence pour les opérateurs eSIM. Prix réels, paiements désactivés. Lancer votre propre opérateur →
Travel eSIM · demo
Français

Guide de l'opérateur

Sommaire

Ce guide vous mène d'un serveur vide à votre première vente, puis couvre le travail quotidien : commandes, remboursements, solde, sauvegardes, mises à jour. Prévoyez une heure pour l'installation. L'essentiel de cette heure, c'est attendre le compte de gros et l'enregistrement DNS.

Autres documents : présentation · guide pour les agents · prise en main · intégrations · SDK

1. Ce que vous installez

            https://esim.example.com
                      │
                   Caddy (80, 443, Let's Encrypt)
      ┌───────────────┼──────────────────────────────┐
      │               │                              │
   store          rails (/agents/*)              node (/.well-known/ai-market.json, /ai-market/*)
 achats des gens  achats des agents via x402     les hubs trouvent vos offres
      │               │
      └──── votre solde eSIM Access ────┘      les paiements vont sur vos portefeuilles

store et rails achètent sur le même compte de gros. Aucun des deux ne détient d'argent : les acheteurs paient à vos adresses, et le kit ne fait que lire les réseaux pour voir arriver les paiements.

2. Avant de commencer

Il vous fautRemarques
Un compte eSIM AccessInscription sur esimaccess.com. Étape 3.
50 $ ou plus sur le soldeLa première recharge est d'au moins 50 $ (carte, PayPal ou Alipay ; virement bancaire à partir de 3 000 $).
Un serveur LinuxDocker Engine avec le plugin compose, une IPv4 publique, ports 80 et 443 ouverts. 1 vCPU et 1 Go de mémoire suffisent.
Un domaine ou sous-domainePar exemple esim.example.com, avec un enregistrement A vers le serveur.
Des adresses de portefeuilleEVM (une adresse pour les sept réseaux EVM), Tron, Solana, TON. N'importe quelle combinaison convient.
Des CGV et une politique de confidentialitéDeux pages publiques. eSIM Access attend que le site de chaque revendeur y renvoie.
Facultatif : une clé Coinbase Developer PlatformActive l'USDC sans gas sur Base pour les personnes et les commandes x402 des agents. Étape 8.
Facultatif : StripeActive les cartes. Étape 8.

3. Le compte de gros

  1. Inscrivez-vous sur esimaccess.com et confirmez votre e-mail.
  2. Rechargez le solde (dans la console : solde, puis recharge). Le minimum est de 50 $. Chaque eSIM vendue est payée sur ce solde au prix de gros : c'est votre stock, pas une commission.
  3. Ouvrez la section développeur (API) de la console. Elle affiche deux valeurs : l'AccessCode et la SecretKey. Traitez la SecretKey comme un mot de passe.

Il n'y a pas de bac à sable : chaque commande API est réelle. Deux façons de tester à peu de frais :

4. Le serveur et le domaine

  1. Créez un enregistrement A de votre domaine vers l'IPv4 du serveur. Vérifiez depuis votre ordinateur :
dig +short esim.example.com
  1. Installez Docker sur le serveur (docs.docker.com/engine/install) et vérifiez que compose fonctionne :
docker compose version
  1. Ouvrez les ports 80 et 443 dans le pare-feu du serveur et dans le panneau de votre hébergeur. Let's Encrypt vérifie le port 80 avant d'émettre le certificat.

5. Récupérez le kit et configurez-le

git clone https://github.com/alexar76/esim-operator-kit.git
cd esim-operator-kit
cp .env.example .env
nano .env
RéglageQuoi mettre
DOMAINVotre domaine, sans https://.
STORE_NAMELe nom que voient les acheteurs dans l'en-tête, le titre et la fenêtre du portefeuille.
PRODUCT_IDUn identifiant court de vos offres dans la fédération, par exemple esim-mytravel. Lettres, chiffres, tirets.
STORE_CONTACTL'e-mail auquel écrivent les acheteurs. Affiché en pied de page.
STORE_TERMS_URL, STORE_PRIVACY_URLVos CGV et votre politique de confidentialité. Liées en pied de page.
MARGIN_PCTVotre marge sur le prix de gros, en pourcentage. 100 le double.
MIN_MARGIN_USDLa marge minimale par eSIM, en dollars. Les forfaits bon marché prennent au moins cela en plus.
DEMO_MODE1 affiche un bandeau et n'encaisse rien. 0 vend. Gardez 1 jusqu'à l'étape 10.
PAY_TO_EVM, PAY_TO_TON, PAY_TO_TRON, PAY_TO_SOLANAVos adresses de réception. Une ligne vide désactive ce réseau.
EVM_CHAINSLes réseaux EVM proposés, par chain id : 8453 Base, 1 Ethereum, 42161 Arbitrum, 10 OP, 137 Polygon, 56 BNB Chain, 43114 Avalanche.
EVM_RPC_<chain id>, SOLANA_RPCFacultatif : vos propres points d'accès RPC. Les publics sont limités en débit.
SUPPLIERD'où viennent les eSIM : esimaccess (par défaut), airalo, esimgo ou http pour votre propre système. Voir intégrations.
WEBHOOK_URL, WEBHOOK_SECRET_FILEFacultatif : le statut de chaque commande, signé, vers votre CRM, votre facturation, Telegram ou un tableur. Voir intégrations.

Comment le prix est calculé. Prix = gros × (1 + MARGIN_PCT/100), mais jamais moins que gros + MIN_MARGIN_USD. Arrondi au centime supérieur. Avec les valeurs par défaut (100 % et 1,00 $), la France 1 Go pour 7 jours coûte 0,70 $ en gros et se vend 1,70 $. Un forfait de 20 Go à 9,00 $ en gros se vend 18,00 $. Les boutiques eSIM de détail demandent souvent de 4 à 8 $ pour les petits forfaits : vous avez de la marge.

Des adresses seulement. Chaque PAY_TO_* est une adresse de réception. Le kit n'a jamais besoin d'une clé privée ni d'une phrase de récupération. Si un guide ou une personne vous demande d'en mettre une dans .env, c'est une erreur.

6. Placez les clés

Les clés vivent dans secrets/, une valeur par fichier. Le dossier est hors git et monté en lecture seule dans les conteneurs. Saisissez les valeurs sans qu'elles atterrissent dans l'historique du shell :

cd ~/esim-operator-kit
umask 077
printf 'AccessCode: '; read -rs v; printf %s "$v" > secrets/esimaccess_access_code; echo
printf 'SecretKey: '; read -rs v; printf %s "$v" > secrets/esimaccess_secret_key; echo
unset v

Les conteneurs tournent sous l'utilisateur 1000 : donnez-lui les fichiers de clés et les dossiers de données :

mkdir -p data/store data/rails data/node data/caddy
sudo chown 1000:1000 secrets/*
sudo chown -R 1000:1000 data/store data/rails data/node
ls -l secrets

Le dossier lui-même reste à vous : vous pourrez ajouter des fichiers plus tard. Chaque nouveau fichier de clé demande le même sudo chown 1000:1000 et chmod 600.

secrets/README.md liste tous les fichiers facultatifs : la clé CDP, les clés tonapi et TronGrid, les clés Stripe.

7. Démarrez en mode démo

docker compose up -d --build
docker compose ps
docker compose logs --tail 30 store rails

La première construction prend quelques minutes. Vérifiez ensuite trois choses :

curl -s https://esim.example.com/agents/healthz
curl -s -X POST https://esim.example.com/agents/quote -H 'content-type: application/json' \
  -d '{"country":"FR","min_gb":3,"min_days":7,"limit":3}'

Si la réponse de santé indique "ok":false, les clés de gros sont fausses ou illisibles. Voir la section 14.

Vérifiez vos prix. Cette commande affiche votre solde et les meilleures offres des pays de votre choix, à votre marge, avec le prix de gros à côté :

docker compose exec -T rails node scripts/catalog.mjs FR ES IT US JP TH

Modifiez MARGIN_PCT ou MIN_MARGIN_USD dans .env et appliquez avec docker compose up -d.

8. Paiements

Chaque moyen s'active dès que son adresse (et sa clé, si besoin) est renseignée. Activez ceux qu'utilisent vos acheteurs. L'USDT sur Tron est la façon la plus courante de payer en crypto ; viennent ensuite l'USDT et l'USDC sur les réseaux EVM et l'USDT sur TON.

MoyenÀ renseignerComment paie l'acheteurComment la vitrine confirme
USDC sur Base, sans gasPAY_TO_EVM + secrets/cdp_api_key.jsonSigne un message dans un portefeuille du navigateur et ne paie pas de gas.Le facilitateur CDP règle la signature. L'eSIM est livrée d'abord, puis le paiement est réglé ; si le règlement échoue, l'eSIM est annulée.
USDC / USDT sur 7 réseaux EVMPAY_TO_EVM (+ EVM_CHAINS)Envoie le virement depuis un portefeuille du navigateur, ou depuis n'importe quel portefeuille ou plateforme d'échange, et colle le hash de la transaction.Lit le reçu : un transfert de ce jeton vers vous, d'au moins le prix, plus récent que la commande. Attend les confirmations : 3 sur Ethereum et BNB Chain, 10 sur Polygon, 1 ailleurs. Une transaction paie une commande.
USDT sur TronPAY_TO_TRON (+ secrets/trongrid_key)Envoie exactement le montant affiché, depuis TronLink sur la page ou depuis n'importe quel portefeuille.Chaque commande demande le prix plus quelques millionièmes de dollar (0,0099 $ de plus au maximum). Ce montant exact identifie la commande parmi vos transferts USDT confirmés.
USDC sur SolanaPAY_TO_SOLANA (+ SOLANA_RPC)Ouvre le lien Solana Pay ou scanne son QR code (Phantom, Solflare, Backpack).Chaque commande a sa propre clé de référence, que le portefeuille ajoute au transfert. La vitrine retrouve la transaction grâce à elle.
USDT ou TON sur TONPAY_TO_TON (+ secrets/tonapi_key)Connecte Tonkeeper ou un autre portefeuille via TON Connect, ou paie à la main avec le commentaire indiqué.Retrouve le transfert par le commentaire de la commande via tonapi.io.
Cartessecrets/stripe_secret_key + secrets/stripe_webhook_secretStripe Checkout.Le webhook Stripe.

Un paiement envoyé (tous les moyens sauf Base sans gas et les cartes) est recherché pendant 24 heures après la création de la commande.

Clé Coinbase Developer Platform. Elle active l'USDC sans gas sur Base pour les personnes et les commandes x402 des agents. Sans elle, la vitrine accepte encore l'USDC sur Base en simple virement, mais le nœud pour agents ne prend aucune commande.

  1. Connectez-vous sur portal.cdp.coinbase.com et créez un projet.
  2. API Keys : créez une clé API secrète et téléchargez son fichier JSON.
  3. Copiez le fichier dans secrets/cdp_api_key.json (il contient id et privateKey), puis lancez sudo chown 1000:1000 secrets/cdp_api_key.json && sudo chmod 600 secrets/cdp_api_key.json et docker compose up -d.

Stripe. Dans le tableau de bord Stripe, ajoutez un point de terminaison webhook https://<votre domaine>/api/stripe/webhook avec les événements checkout.session.completed et checkout.session.async_payment_succeeded. Mettez la clé secrète (sk_live_…) dans secrets/stripe_secret_key et le secret de signature du point de terminaison (whsec_…) dans secrets/stripe_webhook_secret.

Limites de débit. Les points d'accès publics TronGrid, tonapi et RPC suffisent pour une petite boutique. Quand les ventes deviennent régulières, ajoutez une clé TronGrid gratuite et une clé tonapi, et pointez EVM_RPC_<id> et SOLANA_RPC vers votre propre fournisseur.

9. Agents et fédération

Le nœud rails répond déjà aux agents sur https://<votre domaine>/agents/. Pour que les agents vous trouvent en cherchant sur un hub, décrivez votre nœud à la fédération et annoncez-le.

  1. Générez node.toml à partir de votre catalogue réel. Mettez votre nom, votre domaine et votre PRODUCT_ID :
docker compose exec -T rails node scripts/node-toml.mjs \
  --name "My Travel eSIM" --url https://esim.example.com \
  --product esim-mytravel --upstream http://rails:9490 > node.toml
head -20 node.toml
  1. Démarrez le nœud :
docker compose --profile federation up -d --build node
curl -s https://esim.example.com/.well-known/ai-market.json | head -c 400; echo
  1. Vérifiez-le comme le fera un hub, puis annoncez-le :
docker compose exec node aimarket doctor --url https://esim.example.com
docker compose exec node aimarket node knock --config /node/node.toml --hub https://modelmarket.dev

Avant de vous référencer, le hub appelle esim.quote avec un vrai pays. Une fois référencé, un agent qui cherche « eSIM France » sur le hub obtient vos offres. Le paiement ne passe jamais par le hub : l'agent paie votre nœud via x402, directement sur votre portefeuille.

data/node/ contient la clé de signature du nœud, son identité dans la fédération. Sauvegardez-la. Refaites le point 1 quand le catalogue gagne des pays.

10. La commande test, puis la mise en vente

  1. Dans .env, mettez DEMO_MODE=0 et revérifiez les adresses PAY_TO_*, caractère par caractère.
  2. Appliquez :
docker compose up -d
curl -s https://esim.example.com/agents/healthz

"demo":false doit apparaître. "paid_orders":true apparaît quand la clé CDP et PAY_TO_EVM sont renseignées.

  1. Achetez le forfait le moins cher d'un pays dans votre propre boutique, avec votre propre portefeuille, sur le réseau que vos acheteurs utiliseront le plus selon vous. La page de commande doit afficher le QR code en moins d'une minute.
  2. Vérifiez le paiement dans votre portefeuille et la commande dans la console eSIM Access.
  3. Si vous ne voulez pas garder l'eSIM, annulez le profil non utilisé dans la console eSIM Access. Le prix de gros revient sur votre solde. Votre paiement est de toute façon allé sur votre propre portefeuille.

Faites de même pour chaque réseau activé. Vous êtes alors en vente.

11. Au quotidien

Commandes. La vitrine les garde dans data/store/orders.json. Listez celles qui demandent votre attention :

sudo jq -r '.[] | select(.status=="refund_due" or .status=="underpaid")
  | [.created_at, .id, .status, .method, (.price_cents/100), .payment.ref, (.payment.payer // "-"), (.error // "")] | @tsv' \
  data/store/orders.json
StatutSignificationQue faire
awaiting_paymentLa commande existe, rien n'est encore arrivé.Rien.
deliveredPayée, l'eSIM est chez l'acheteur.Rien.
refund_duePayée, mais le grossiste n'a pas livré : solde épuisé, ou forfait retiré.Remboursez l'acheteur à payment.payer sur le même réseau, ou rechargez et vendez-lui le forfait à la main.
underpaidUn paiement inférieur au prix est arrivé.Remboursez-le, ou demandez la différence à l'acheteur et livrez à la main.
expiredRien n'est arrivé en 24 heures.Rien. Un paiement arrivé plus tard n'est pas rapproché ; vous le verrez sur votre portefeuille sans commande.

Les acheteurs écrivent à STORE_CONTACT. Demandez-leur le numéro de commande dans l'adresse de leur page (/o/<numéro>). Ne demandez pas le lien complet : il contient leur jeton.

Solde. Gardez le solde de gros au-dessus de quelques jours de ventes. Quand il ne couvre pas une commande, le paiement indique « Ce forfait est temporairement indisponible » au lieu d'encaisser. Vérifiez-le avec :

docker compose exec -T rails node scripts/catalog.mjs | head -1

Journaux.

docker compose logs -f --tail 100 store rails

Les journaux ne contiennent jamais de code d'activation ni de clé.

Sauvegardes. Sauvegardez data/ et secrets/ chaque jour, ailleurs que sur le serveur :

Mises à jour.

git pull
docker compose up -d --build
docker compose --profile federation up -d --build node    # si vous utilisez le nœud de fédération

Lisez les notes de version avant de mettre à jour une boutique qui vend.

12. Commandes des agents

Les agents achètent via POST /agents/order (voir le guide pour les agents). Le nœud vérifie le paiement x402, achète le profil et ne règle qu'une fois le profil créé. Si le règlement échoue, il annule le profil et le prix de gros revient sur votre solde. Les commandes des agents sont enregistrées dans data/rails/orders.json, sans codes d'activation. Les USDC arrivent sur PAY_TO_EVM sur Base.

13. Droit, taxes et conditions

Ceci n'est pas un conseil juridique ou fiscal. Consultez un comptable dans votre pays avant de vendre.

14. Dépannage

Ce que vous voyezCauseSolution
Le navigateur dit que le certificat n'est pas valideLe DNS ne pointe pas encore ici, ou le port 80 est fermédig +short <domaine>, ouvrez le port 80, puis docker compose restart caddy et lisez docker compose logs caddy.
healthz affiche "ok":false ou la boutique n'affiche aucun paysLes clés de gros sont fausses ou l'utilisateur 1000 ne peut pas les lire. Les journaux disent catalogue not loaded yet: <code>.sudo rm secrets/esimaccess_*, réécrivez-les comme à l'étape 6, puis docker compose restart store rails.
EACCES ou permission denied dans les journauxLes dossiers de données n'appartiennent pas à l'utilisateur 1000sudo chown -R 1000:1000 data/store data/rails data/node
Le paiement indique « Ce forfait est temporairement indisponible »Le solde de gros ne couvre pas le forfaitRechargez eSIM Access.
Chaque paiement répond « Mode démo : les paiements sont désactivés »DEMO_MODE=1Étape 10.
Un réseau manque au paiementSon PAY_TO_* est videVérifiez .env, puis docker compose up -d.
La vitrine redémarre en boucleUn PAY_TO_* n'est pas une adresse valide : la vitrine refuse de démarrer avecdocker compose logs store la nomme. Corrigez .env.
Un paiement Tron est introuvableLe montant n'était pas exact, souvent parce qu'une plateforme d'échange en a déduit ses fraisRetrouvez le transfert sur votre portefeuille et remboursez-le, ou livrez à la main. Demandez aux acheteurs d'envoyer le montant exact depuis un portefeuille.
Un paiement TON est introuvableLe commentaire manquait ou a été modifiéComme ci-dessus. Avec TON Connect, le portefeuille remplit le commentaire tout seul.
aimarket doctor signale une adresse privéeL'url de node.toml n'est pas votre domaine publicRégénérez node.toml (étape 9) avec --url https://<domaine>.
node ne démarre pas : node.toml est un dossierCompose l'a créé parce que le fichier n'existait pasrmdir node.toml, générez le fichier (étape 9), redémarrez.

Le kit sur GitHub →