Демо-режим: референсная витрина для eSIM-операторов. Цены живые, оплата отключена. Запустить своего оператора →
Travel eSIM · demo
Русский

Гайд оператора

Содержание

Гайд ведёт от пустого сервера до первой продажи, а затем описывает ежедневную работу: заказы, возвраты, баланс, бэкапы, обновления. На настройку заложите час. Большая часть этого часа уходит на ожидание оптового аккаунта и DNS-записи.

Другие документы: обзор · гайд для агентов · онбординг · интеграции · SDK

1. Что вы поднимаете

            https://esim.example.com
                      │
                   Caddy (80, 443, Let's Encrypt)
      ┌───────────────┼──────────────────────────────┐
      │               │                              │
   store          rails (/agents/*)              node (/.well-known/ai-market.json, /ai-market/*)
 покупают люди   покупают агенты по x402        хабы находят ваши предложения
      │               │
      └──── ваш баланс в eSIM Access ────┘     платежи идут на ваши кошельки

store и rails покупают с одного оптового аккаунта. Ни один из них не держит деньги: покупатели платят на ваши адреса, а кит только читает сети, чтобы увидеть поступление.

2. Перед началом

Что нужноПримечание
Аккаунт в eSIM AccessРегистрация на esimaccess.com. Шаг 3.
От $50 на балансеПервое пополнение — минимум $50 (карта, PayPal или Alipay; банковский перевод — от $3000).
Сервер на LinuxDocker Engine с плагином compose, публичный IPv4-адрес, открытые порты 80 и 443. Хватит 1 vCPU и 1 ГБ памяти.
Домен или поддоменНапример esim.example.com, с A-записью на сервер.
Адреса кошельковEVM (один адрес на все семь EVM-сетей), Tron, Solana, TON. Подойдёт любой набор.
Условия продажи и политика конфиденциальностиДве публичные страницы. eSIM Access ждёт, что сайт каждого реселлера на них ссылается.
Необязательно: ключ Coinbase Developer PlatformВключает USDC в Base без газа для людей и заказы агентов по x402. Шаг 8.
Необязательно: StripeВключает карты. Шаг 8.

3. Оптовый аккаунт

  1. Зарегистрируйтесь на esimaccess.com и подтвердите почту.
  2. Пополните баланс (в консоли: баланс, затем пополнение). Минимум — $50. Каждая проданная eSIM оплачивается с этого баланса по оптовой цене, так что это ваш товарный запас, а не комиссия.
  3. Откройте раздел разработчика (API) в консоли. Там два значения: AccessCode и SecretKey. Обращайтесь с SecretKey как с паролем.

Песочницы нет: каждый заказ через API настоящий. Два способа проверить дёшево:

4. Сервер и домен

  1. Создайте A-запись домена на IPv4-адрес сервера. Проверьте со своего компьютера:
dig +short esim.example.com
  1. Установите Docker на сервер (docs.docker.com/engine/install) и проверьте, что compose работает:
docker compose version
  1. Откройте порты 80 и 443 в файрволе сервера и в панели хостинга. Let's Encrypt проверяет порт 80, прежде чем выдать сертификат.

5. Скачайте кит и настройте его

git clone https://github.com/alexar76/esim-operator-kit.git
cd esim-operator-kit
cp .env.example .env
nano .env
НастройкаЧто указать
DOMAINВаш домен, без https://.
STORE_NAMEНазвание, которое покупатели видят в шапке, заголовке и в окне кошелька.
PRODUCT_IDКороткий идентификатор ваших предложений в федерации, например esim-mytravel. Буквы, цифры, дефисы.
STORE_CONTACTПочта, на которую пишут покупатели. Показывается в подвале.
STORE_TERMS_URL, STORE_PRIVACY_URLВаши условия продажи и политика конфиденциальности. Ссылки стоят в подвале.
MARGIN_PCTНаценка на оптовую цену в процентах. 100 удваивает цену.
MIN_MARGIN_USDМинимальная наценка на одну eSIM в долларах. К дешёвым тарифам добавляется не меньше этой суммы.
DEMO_MODE1 — баннер и никаких платежей. 0 — продажа. Держите 1 до шага 10.
PAY_TO_EVM, PAY_TO_TON, PAY_TO_TRON, PAY_TO_SOLANAВаши адреса для приёма. Пустая строка выключает сеть.
EVM_CHAINSКакие EVM-сети предлагать, номерами сетей: 8453 Base, 1 Ethereum, 42161 Arbitrum, 10 OP, 137 Polygon, 56 BNB Chain, 43114 Avalanche.
EVM_RPC_<номер сети>, SOLANA_RPCНеобязательно: ваши RPC-адреса. У публичных есть лимиты запросов.
SUPPLIERОткуда берутся eSIM: esimaccess (по умолчанию), airalo, esimgo или http для вашей собственной системы. См. интеграции.
WEBHOOK_URL, WEBHOOK_SECRET_FILEНеобязательно: статус каждого заказа, с подписью, в вашу CRM, биллинг, Telegram или таблицу. См. интеграции.

Как считается цена. Цена = опт × (1 + MARGIN_PCT/100), но не меньше опт + MIN_MARGIN_USD. Округление — вверх до цента. С настройками по умолчанию (100 % и $1.00) Франция 1 ГБ на 7 дней стоит $0.70 оптом и продаётся за $1.70. Тариф на 20 ГБ за $9.00 оптом продаётся за $18.00. Розничные eSIM-магазины обычно берут $4–8 за маленькие тарифы, так что запас есть.

Только адреса. Каждый PAY_TO_* — адрес, на который вы принимаете. Киту никогда не нужен приватный ключ или сид-фраза. Если инструкция или человек просит положить их в .env, это ошибка.

6. Положите ключи

Ключи лежат в secrets/, по одному значению в файле. Папка исключена из git и монтируется в контейнеры только для чтения. Введите значения так, чтобы они не попали в историю команд:

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

Контейнеры работают от пользователя 1000, поэтому отдайте ему файлы ключей и папки данных:

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

Сама папка остаётся вашей, так что файлы можно добавлять и позже. Каждому новому файлу ключа нужны те же sudo chown 1000:1000 и chmod 600.

В secrets/README.md перечислены все необязательные файлы: ключ CDP, ключи tonapi и TronGrid, ключи Stripe.

7. Запуск в демо-режиме

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

Первая сборка занимает несколько минут. Затем проверьте три вещи:

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}'

Если проверка отвечает "ok":false, оптовые ключи неверны или не читаются. См. раздел 14.

Проверьте цены. Команда печатает баланс и лучшие предложения по любым странам с вашей наценкой, рядом с каждым — оптовая цена:

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

Поменяйте MARGIN_PCT или MIN_MARGIN_USD в .env и примените: docker compose up -d.

8. Платежи

Каждый способ включается, когда задан его адрес (и ключ, где он нужен). Включите те, которыми пользуются ваши покупатели. USDT в Tron — самый частый способ платить криптой; за ним идут USDT и USDC в EVM-сетях и USDT в TON.

СпособЧто задатьКак платит покупательКак витрина подтверждает
USDC в Base без газаPAY_TO_EVM + secrets/cdp_api_key.jsonПодписывает одно сообщение в браузерном кошельке и не платит за газ.Подпись проводит фасилитатор CDP. Сначала выдаётся eSIM, потом проводится платёж; если проведение не удалось, eSIM отменяется.
USDC / USDT в 7 EVM-сетяхPAY_TO_EVM (+ EVM_CHAINS)Отправляет перевод из браузерного кошелька или из любого кошелька или биржи и вставляет хеш транзакции.Читает квитанцию: перевод этого токена вам, не меньше цены, новее заказа. Ждёт подтверждений: 3 в Ethereum и BNB Chain, 10 в Polygon, 1 в остальных. Одна транзакция оплачивает один заказ.
USDT в TronPAY_TO_TRON (+ secrets/trongrid_key)Отправляет ровно указанную сумму, из TronLink на странице или из любого кошелька.Каждый заказ просит цену плюс несколько миллионных долларов (не больше $0.0099 сверху). Эта точная сумма и опознаёт заказ среди ваших подтверждённых переводов USDT.
USDC в SolanaPAY_TO_SOLANA (+ SOLANA_RPC)Открывает ссылку Solana Pay или сканирует её QR-код (Phantom, Solflare, Backpack).У каждого заказа свой ключ-референс, кошелёк добавляет его в перевод. Витрина находит транзакцию по нему.
USDT или TON в TONPAY_TO_TON (+ secrets/tonapi_key)Подключает Tonkeeper или другой кошелёк через TON Connect либо платит вручную с указанным комментарием.Находит перевод по комментарию заказа через tonapi.io.
Картыsecrets/stripe_secret_key + secrets/stripe_webhook_secretStripe Checkout.Вебхук Stripe.

Отправленный платёж (все способы, кроме Base без газа и карт) ищется в течение 24 часов после создания заказа.

Ключ Coinbase Developer Platform. Он включает USDC в Base без газа для людей и заказы агентов по x402. Без него витрина всё равно принимает USDC в Base обычным переводом, но узел для агентов заказы не принимает.

  1. Войдите на portal.cdp.coinbase.com и создайте проект.
  2. API Keys: создайте секретный API-ключ и скачайте его JSON-файл.
  3. Скопируйте файл в secrets/cdp_api_key.json (в нём id и privateKey), затем выполните sudo chown 1000:1000 secrets/cdp_api_key.json && sudo chmod 600 secrets/cdp_api_key.json и docker compose up -d.

Stripe. В панели Stripe добавьте вебхук https://<ваш домен>/api/stripe/webhook с событиями checkout.session.completed и checkout.session.async_payment_succeeded. Секретный ключ (sk_live_…) положите в secrets/stripe_secret_key, а секрет подписи вебхука (whsec_…) — в secrets/stripe_webhook_secret.

Лимиты запросов. Публичных TronGrid, tonapi и RPC хватает небольшому магазину. Когда продажи станут регулярными, добавьте бесплатный ключ TronGrid и ключ tonapi, а EVM_RPC_<номер> и SOLANA_RPC направьте на своего провайдера.

9. Агенты и федерация

Узел rails уже отвечает агентам по адресу https://<ваш домен>/agents/. Чтобы агенты находили вас поиском на хабе, опишите узел для федерации и анонсируйте его.

  1. Сгенерируйте node.toml из живого каталога. Подставьте своё название, домен и 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. Запустите узел:
docker compose --profile federation up -d --build node
curl -s https://esim.example.com/.well-known/ai-market.json | head -c 400; echo
  1. Проверьте его так, как проверит хаб, и анонсируйте:
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

Перед тем как внести вас в каталог, хаб вызывает esim.quote с настоящей страной. После этого агент, который ищет на хабе «eSIM France», получает ваши предложения. Оплата никогда не идёт через хаб: агент платит вашему узлу по x402, прямо на ваш кошелёк.

В data/node/ лежит ключ подписи узла — это его идентичность в федерации. Сделайте бэкап. Повторите пункт 1, когда в каталоге появятся новые страны.

10. Тестовый заказ и запуск продаж

  1. В .env поставьте DEMO_MODE=0 и ещё раз сверьте адреса PAY_TO_* символ за символом.
  2. Примените:
docker compose up -d
curl -s https://esim.example.com/agents/healthz

Должно быть "demo":false. "paid_orders":true появляется, когда заданы ключ CDP и PAY_TO_EVM.

  1. Купите самый дешёвый тариф какой-нибудь страны в своей витрине, своим кошельком, в той сети, которой, по-вашему, чаще всего будут платить покупатели. QR-код должен появиться на странице заказа в течение минуты.
  2. Проверьте платёж в кошельке и заказ в консоли eSIM Access.
  3. Если eSIM вам не нужна, отмените неиспользованный профиль в консоли eSIM Access. Оптовая цена вернётся на баланс. Ваш платёж всё равно ушёл на ваш же кошелёк.

Повторите для каждой включённой сети. После этого вы в деле.

11. Ежедневная работа

Заказы. Витрина хранит их в data/store/orders.json. Список тех, что требуют вашего внимания:

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
СтатусЗначениеЧто делать
awaiting_paymentЗаказ создан, денег пока нет.Ничего.
deliveredОплачен, eSIM у покупателя.Ничего.
refund_dueОплачен, но оптовик не выдал eSIM: кончился баланс или тариф сняли с продажи.Верните деньги покупателю на payment.payer в той же сети или пополните баланс и продайте ему тариф вручную.
underpaidПришло меньше цены.Верните платёж или попросите покупателя доплатить и выдайте вручную.
expiredЗа 24 часа ничего не пришло.Ничего. Платёж, пришедший позже, не сопоставляется: вы увидите его в кошельке без заказа.

Покупатели пишут на STORE_CONTACT. Просите у них номер заказа из адреса страницы (/o/<номер>). Не просите полную ссылку: в ней их токен.

Баланс. Держите оптовый баланс выше продаж за несколько дней. Когда его не хватает на заказ, оплата пишет «Тариф временно недоступен» и не берёт деньги. Проверить баланс:

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

Логи.

docker compose logs -f --tail 100 store rails

В логах никогда нет кодов активации и ключей.

Бэкапы. Ежедневно сохраняйте data/ и secrets/ куда-нибудь вне сервера:

Обновления.

git pull
docker compose up -d --build
docker compose --profile federation up -d --build node    # если запускаете узел федерации

Читайте заметки к выпуску, прежде чем обновлять магазин, который продаёт.

12. Заказы агентов

Агенты покупают через POST /agents/order (см. гайд для агентов). Узел проверяет платёж x402, покупает профиль и проводит платёж только после того, как профиль создан. Если проведение не удалось, профиль отменяется, а оптовая цена возвращается на баланс. Заказы агентов записываются в data/rails/orders.json, без кодов активации. USDC приходят на PAY_TO_EVM в сети Base.

13. Законы, налоги и условия

Это не юридическая и не налоговая консультация. Прежде чем продавать, спросите бухгалтера в своей стране.

14. Решение проблем

Что видноПричинаЧто делать
Браузер говорит, что сертификат недействителенDNS ещё не указывает сюда или закрыт порт 80dig +short <домен>, откройте порт 80, затем docker compose restart caddy и смотрите docker compose logs caddy.
healthz показывает "ok":false или на витрине нет странОптовые ключи неверны или пользователь 1000 не может их прочитать. В логах catalogue not loaded yet: <code>.sudo rm secrets/esimaccess_*, запишите их заново, как в шаге 6, затем docker compose restart store rails.
В логах EACCES или permission deniedПапки данных принадлежат не пользователю 1000sudo chown -R 1000:1000 data/store data/rails data/node
Оплата пишет «Тариф временно недоступен»Оптового баланса не хватает на тарифПополните eSIM Access.
Каждый платёж отвечает «Демо-режим: оплата отключена»DEMO_MODE=1Шаг 10.
Сети нет в оплатеЕё PAY_TO_* пустойПроверьте .env, затем docker compose up -d.
Витрина перезапускается снова и сноваКакой-то PAY_TO_* — неверный адрес: с ним витрина отказывается стартоватьdocker compose logs store назовёт его. Исправьте .env.
Платёж в Tron не найденСумма была не точной, часто потому что биржа вычла из неё свою комиссиюНайдите перевод в кошельке и верните его или выдайте вручную. Просите покупателей отправлять точную сумму из кошелька.
Платёж в TON не найденКомментарий не указан или изменёнТак же, как выше. С TON Connect кошелёк подставляет комментарий сам.
aimarket doctor сообщает о приватном адресеurl в node.toml — не ваш публичный доменСгенерируйте node.toml заново (шаг 9) с --url https://<домен>.
node не стартует: node.toml — это папкаCompose создал её, потому что файла не былоrmdir node.toml, сгенерируйте файл (шаг 9), запустите снова.

Кит на GitHub →