# 08. Интеграции ## 1. Почта (этап 1c) 1. Шаблоны — в Payload (`email-templates`): тема и текст на каждом языке, для каждого сайта свои. Шапка (логотип) и подвал (контакты, юридические ссылки) — в коде, у каждого бренда свои. 2. Отправка — через email-адаптер Payload на Nodemailer. Транспорт переключается в админке (глобал «Почта»): a. `smtp` — внешний SMTP-провайдер (данные в настройках, пароль зашифрован); b. `sendmail` — локальный Postfix (`/usr/sbin/sendmail`); c. `log_only` — не отправлять, только записать в журнал (для разработки). 3. Письма уходят через фоновую задачу `send-email` с повторами при ошибке. Каждое письмо пишется в журнал писем; коды входа — по флагу ([05-auth.md](05-auth.md), раздел 4). 4. Кнопка «Отправить тестовое письмо» проверяет текущий транспорт. 5. Чтобы письма через Postfix не попадали в спам (root, [09-infrastructure.md](09-infrastructure.md), раздел 6): a. Postfix отправляет с IP 169.58.76.183 под именем `fr-ub2gs3.veilix.cc` — у этого IP прямая и обратная DNS-записи совпадают; b. для veilix.app и veilixvpn.com нужны SPF, DKIM (OpenDKIM уже установлен) и DMARC; c. проверить, что исходящий порт 25 открыт и IP нет в чёрных списках. 6. Новые IP почтовые сервисы поначалу принимают настороженно, поэтому SMTP-провайдер держим запасным вариантом. ## 2. ALTCHA (этап 1c) 1. Капча на proof-of-work без сторонних сервисов: браузер решает небольшую вычислительную задачу, сервер проверяет подпись. 2. Эндпоинт выдачи задачи — `/svc/altcha/challenge`, ключ подписи — в `.env`. 3. Где: запрос кода входа, формы заявок и обратной связи. 4. Вместе с лимитами по IP и email ([05-auth.md](05-auth.md)). Провайдер капчи изолирован в `core/`, его можно заменить. ## 3. MaxMind (этап 1a) 1. Модуль nginx `geoip2` (уже установлен) определяет страну по базе GeoLite2-Country и передаёт её приложению заголовком `X-Geo-Country`. Клиентский заголовок с таким именем nginx перезаписывает. 2. База обновляется `geoipupdate` по таймеру (root, нужен бесплатный аккаунт MaxMind). Модуль nginx перечитывает базу сам (`auto_reload`). 3. Страна используется только для выбора языка по умолчанию, не для валюты. 4. Если понадобится страна произвольного IP (антифрод), приложение читает тот же `.mmdb` библиотекой `maxmind`. ## 4. Chatwoot (этап 2) 1. Один экземпляр на отдельном VPS обслуживает оба бренда. У каждого бренда свои входящие каналы: a. виджет на сайте и в кабинете; b. бот поддержки в Telegram, подключённый к Chatwoot напрямую как Telegram-канал; c. почта `help@…`: email-канал Chatwoot забирает письма из ящика на почтовом хостинге по IMAP и отвечает через его SMTP ([09-infrastructure.md](09-infrastructure.md), раздел 6). 2. Для вошедших пользователей виджет получает идентификацию с HMAC-подписью: оператор видит, кто пишет, а подделать её нельзя. Передаём атрибуты: сайт, id пользователя, email, число ключей. 3. Почему бот поддержки отдельный: Telegram отдаёт обновления одного бота только одному получателю. Основной бот принадлежит нашему приложению, бот поддержки — Chatwoot. ## 5. Twenty CRM (этап 2) 1. Заявки из `leads` уходят в Twenty через API: человек и сделка с полями заявки, брендом и страницей. Отправка — фоновой задачей с повторами; id в Twenty сохраняется в `leads.crmId`. 2. До этапа 2 заявки видны в админке Payload и приходят письмом `admin_new_lead` на почту поддержки. ## 6. Telegram (этап 3) 1. Боты для каждого бренда: a. основной: команды, кнопка MiniApp, уведомления. Код — grammY в нашем приложении, вебхук `/svc/telegram/<сайт>/webhook` с секретным токеном; b. поддержки: подключён к Chatwoot. Для dev — отдельные тестовые боты. 2. MiniApp — на tg.*, вход по `initData` ([05-auth.md](05-auth.md), раздел 6). Dev-MiniApp доступна только Telegram-аккаунтам из списка разрешённых. 3. Черновик команд основного бота: `/start` (в том числе с реферальным кодом или токеном привязки), `/keys`, `/buy`, `/balance`, `/topup`, `/referral`, `/language`, `/support` (ссылка на бота поддержки), `/help`. Тексты и кнопки — в Payload, локализованные. 4. Уведомления из [04-billing.md](04-billing.md) (раздел 12) дублируются в бот, если Telegram привязан. 5. Оплата в Telegram (Q-11): по правилам Telegram цифровые товары в ботах и MiniApp оплачиваются Telegram Stars, за нарушения ботов блокируют. Варианты: Stars, внешняя страница оплаты, покупки в Telegram только с баланса. Решаем на старте этапа. ## 7. Платёжные системы 1. Каждый провайдер — адаптер в `core/payments/` с единым интерфейсом: a. `createPayment` — создать платёж и вернуть адрес страницы оплаты или данные виджета; b. `handleWebhook` — проверить подпись и вернуть новый статус платежа; c. по возможностям: `chargeSavedMethod` (автосписание), `refund`, `detachMethod`. 2. Запись в коллекции `payment-systems` включает адаптер в валютах и для назначений ([03-data-model.md](03-data-model.md), 3.4). На каком сайте система доступна, следует из валют его доменов. Ключи доступа — в `.env`. 3. Этап 1: только `manual` — для администраторов. 4. Этап 4: a. Stripe — USD: карты, сохранение карты, автосписания без участия пользователя на переменную сумму («цена минус баланс»), без Stripe Subscriptions. Сначала тестовый режим; b. RUB — процессинги, принимающие карты РФ (вероятно, KZ и TR), только пополнения. Провайдеров выбираем на этапе (Q-12); c. криптовалюта — пополнения в RUB и USD, провайдер выбирается на этапе; d. ЮKassa — опционально, только пополнения, если примет категорию. 5. Вебхуки — `/svc/payments/<адаптер>/webhook`; обработка идемпотентная ([04-billing.md](04-billing.md), раздел 14). ## 8. Umami и баннер cookies (этап 1h) 1. Umami — своя аналитика без cookies, данные не уходят третьим лицам ([D-018](decisions/D-018-analytics.md)). a. Ставится на этот сервер из исходников, без Docker: Node.js и PostgreSQL здесь уже есть. Umami 3.x поддерживает только PostgreSQL. b. Отдельный пользователь ОС `umami`, своя база `umami`, systemd user-юнит, порт 3300. c. Панель — `umi.veilix.cc`, доступ только с разрешённых IP. 2. Скрипт и отправка событий проксируются через домены брендов под нейтральными путями (переменные Umami `TRACKER_SCRIPT_NAME` и `COLLECT_API_ENDPOINT`), чтобы их не резали блокировщики рекламы. Реальный IP посетителя Umami берёт из заголовка nginx (`CLIENT_IP_HEADER`). Телеметрия Umami выключена (`DISABLE_TELEMETRY=1`). 3. Баннер cookies: обязательные (сессия, язык, валюта) и функциональные (чат Chatwoot). Решение пользователя хранится в cookie `vx_consent`, необязательные скрипты загружаются только после согласия. Библиотека — vanilla-cookieconsent или своя лёгкая реализация. ## 9. Автоматизация ключей (этап 5) Подбор свободного сервера по тарифу (страны, теги) и автоматическая выдача подключений. Обсуждаем при старте этапа.