feat(admin): вкладка «Инструкции» + русификация статусов в UI
В admin-панели lk-gateway добавлен раздел /admin/help — справка по основным интеграциям, читается прямо на сервере, без выхода во внешнюю документацию. Состав /admin/help: - /admin/help — hub-страница с 4 карточками-ссылками - /admin/help/database — подключение PostgreSQL, схемы fansy/fansy_staging/m2m_core, что подгружается через ETL Fansy и что пишет сама система, роли, миграции, полезные запросы - /admin/help/lk-api — REST-контракт ESIA Finance V1: аутентификация, POST/GET/PATCH/list, формат callback'ов и ошибок, эмулятор для тестов, примеры curl - /admin/help/cryptopro — установка КриптоПро CSP на РЕД ОС и Ubuntu, ввод серийного номера лицензии (cpconfig), путь к PKCS#11 модулю libcppkcs11.so, подключение Рутокен ЭЦП 2.0 для подписи оператора, тестирование подписи через csptest и cryptcp - /admin/help/systems — Интеграционный шлюз НРД (профили guest/test3/prod), команда Fansy (порядок согласования контракта), уведомления (SMTP/Yandex Messenger/Telegram), контакты команд Русификация статусов: - Добавлены template-функции ruState и ruOutcome (в lkgateway и lkemulator) - "draft" → "Черновик", "confirmed" → "Подтверждена", "rejected" → "Отклонена" и т.д. - CSS-классы бейджей сохраняются (по исходному state), меняется только отображаемый текст. Технические термины (PostgreSQL, ИНН, GUID, REST) остаются как есть — они являются именами программного обеспечения. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Заявка <code>{{slice .Claim.ID 0 8}}</code> · <span class="badge {{.Claim.Status}}">{{.Claim.Status}}</span></h2>
|
||||
<h2>Заявка <code>{{slice .Claim.ID 0 8}}</code> · <span class="badge {{.Claim.Status}}">{{ruState .Claim.Status}}</span></h2>
|
||||
<table>
|
||||
<tr><td style="width:200px" class="muted">Создана</td><td>{{.Claim.CreatedAt.Format "02.01.2006 15:04:05"}}</td></tr>
|
||||
<tr><td class="muted">Обновлена</td><td>{{.Claim.UpdatedAt.Format "02.01.2006 15:04:05"}}</td></tr>
|
||||
@@ -39,7 +39,7 @@
|
||||
<tbody>
|
||||
{{range .Claim.Stages}}
|
||||
<tr>
|
||||
<td><span class="badge {{.State}}">{{.State}}</span></td>
|
||||
<td><span class="badge {{.State}}">{{ruState .State}}</span></td>
|
||||
<td>{{.EnteredAt.Format "15:04:05.000"}}</td>
|
||||
<td>{{if .LeftAt}}{{.LeftAt.Format "15:04:05.000"}}{{else}}<span class="muted">сейчас</span>{{end}}</td>
|
||||
<td class="muted">{{.Reason}}</td>
|
||||
@@ -74,7 +74,7 @@
|
||||
{{range .Claim.M2MDecision.Securities}}
|
||||
<tr>
|
||||
<td><code>{{.ReferenceID}}</code></td>
|
||||
<td><span class="badge {{if eq .Outcome "confirmed"}}confirmed{{else}}rejected{{end}}">{{.Outcome}}</span></td>
|
||||
<td><span class="badge {{if eq .Outcome "confirmed"}}confirmed{{else}}rejected{{end}}">{{ruOutcome .Outcome}}</span></td>
|
||||
<td>{{range .RejectCodes}}<code>{{.}}</code> {{end}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
@@ -87,7 +87,7 @@
|
||||
<div class="card">
|
||||
<h2>Последний callback в ЛК</h2>
|
||||
<table>
|
||||
<tr><td style="width:160px" class="muted">Статус</td><td><span class="badge {{.Claim.LastCallback.NewStatus}}">{{.Claim.LastCallback.NewStatus}}</span></td></tr>
|
||||
<tr><td style="width:160px" class="muted">Статус</td><td><span class="badge {{.Claim.LastCallback.NewStatus}}">{{ruState .Claim.LastCallback.NewStatus}}</span></td></tr>
|
||||
{{if .Claim.LastCallback.ReasonCode}}
|
||||
<tr><td class="muted">Код причины</td><td><code>{{.Claim.LastCallback.ReasonCode}}</code> {{.Claim.LastCallback.ReasonText}}</td></tr>
|
||||
{{end}}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<td>{{len .Securities}}</td>
|
||||
<td><code>{{.TransferringDepositoryINN}}</code></td>
|
||||
<td><code>{{.ReceivingDepositoryINN}}</code></td>
|
||||
<td><span class="badge {{.Status}}">{{.Status}}</span></td>
|
||||
<td><span class="badge {{.Status}}">{{ruState .Status}}</span></td>
|
||||
<td><a href="/admin/claims/{{.ID}}">детали →</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{{define "content"}}
|
||||
<div class="card">
|
||||
<h2>Инструкции и подсказки</h2>
|
||||
<p class="muted">Краткие гайды по основным интеграциям и эксплуатации Bridge-and-Join-s. Открывайте раздел и быстро находите команду или объяснение.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<a href="/admin/help/database" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">База данных →</h2>
|
||||
<p class="muted">PostgreSQL: подключение, схемы <code>fansy</code> / <code>fansy_staging</code> / <code>m2m_core</code>, что подгружается извне (ETL Fansy) и что пишет сама система. Учётные записи, гранты, миграции.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/admin/help/lk-api" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">API личного кабинета →</h2>
|
||||
<p class="muted">REST-контракт ESIA Finance V1: <code>POST /api/v1/back_office/claims/</code>, GET/PATCH-операции, формат callback'ов, аутентификация Basic, примеры запросов curl.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/admin/help/cryptopro" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">КриптоПро и Рутокен →</h2>
|
||||
<p class="muted">Установка КриптоПро CSP на РЕД ОС / Ubuntu, ввод серийного номера, PKCS#11 модуль, серверная подпись и подпись оператора через Рутокен ЭЦП 2.0, тестирование.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/admin/help/systems" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">Внешние системы →</h2>
|
||||
<p class="muted">ИШ НРД (профили GUEST/TEST3/PROD), команда Fansy (ETL в staging), уведомления (e-mail, Yandex Messenger, Telegram), порядок согласования.</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,113 @@
|
||||
{{define "content"}}
|
||||
<p style="margin-bottom:16px"><a href="/admin/help">← все инструкции</a></p>
|
||||
|
||||
<div class="card">
|
||||
<h2>КриптоПро и Рутокен</h2>
|
||||
<p class="muted">Bridge-and-Join-s использует ГОСТ Р 34.10-2012 для подписи и проверки XMLDSig. Серверная криптография — КриптоПро CSP. Подпись оператора в admin-ui — Рутокен ЭЦП 2.0 (опционально). Оба продукта говорят со стандартным интерфейсом PKCS#11, поэтому Go-клиент общается с ними одинаково.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>1. Что и зачем нужно</h2>
|
||||
<table>
|
||||
<thead><tr><th>Сценарий</th><th>СКЗИ</th><th>Цена (ориентир)</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Проверка XMLDSig входящих от НРД и брокеров</td><td>КриптоПро CSP «Сервер»</td><td>~30-50к ₽ (один раз)</td></tr>
|
||||
<tr><td>Подпись пакетов в НРД (резервный канал WS ONYX)</td><td>КриптоПро CSP «Сервер»</td><td>включено</td></tr>
|
||||
<tr><td>Подпись действий оператора в admin-ui</td><td>Рутокен ЭЦП 2.0 + лицензия CSP «Рабочее место»</td><td>~3-5к ₽ железо + ~2-3к ₽ лицензия</td></tr>
|
||||
<tr><td>Проверка XMLDSig заявлений от ЛК</td><td>КриптоПро CSP «Сервер»</td><td>включено</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="muted">Если используется Интеграционный шлюз НРД (ИШ), он сам подписывает пакеты — наша серверная подпись нужна только для резервного канала ONYX и подписи действий оператора. Можно начать с минимума: только Рутокен оператора и отложить серверную лицензию.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>2. Установка КриптоПро CSP на РЕД ОС</h2>
|
||||
<p>Скачать дистрибутив с <code>www.cryptopro.ru</code> (Linux x86_64).</p>
|
||||
<pre>sudo rpm -i cprocsp-rdr-gui-gtk-64-5.0.*.rpm \
|
||||
cprocsp-rdr-64-5.0.*.rpm \
|
||||
cprocsp-ca-certs-64-5.0.*.rpm \
|
||||
lsb-cprocsp-base-5.0.*.rpm \
|
||||
lsb-cprocsp-rdr-64-5.0.*.rpm</pre>
|
||||
<p>Активация лицензии:</p>
|
||||
<pre>sudo /opt/cprocsp/sbin/amd64/cpconfig -license -set XXXX-XXXXX-XXXXX-XXXXX-XXXXX</pre>
|
||||
<p>Проверка:</p>
|
||||
<pre>/opt/cprocsp/sbin/amd64/cpconfig -license -view
|
||||
/opt/cprocsp/bin/amd64/csptest -keyset -enum -unique</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>3. Установка на Ubuntu / Debian</h2>
|
||||
<pre>sudo dpkg -i cprocsp-rdr-gui-gtk-64_5.0.*_amd64.deb \
|
||||
cprocsp-rdr-64_5.0.*_amd64.deb \
|
||||
lsb-cprocsp-base_5.0.*_all.deb \
|
||||
lsb-cprocsp-rdr-64_5.0.*_amd64.deb
|
||||
sudo apt-get install -f
|
||||
sudo /opt/cprocsp/sbin/amd64/cpconfig -license -set XXXX-XXXXX-XXXXX-XXXXX-XXXXX</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>4. PKCS#11 модуль</h2>
|
||||
<p>Путь к библиотеке после установки:</p>
|
||||
<pre>/opt/cprocsp/lib/amd64/libcppkcs11.so</pre>
|
||||
<p>Эта же библиотека работает и с CSP-ключами (контейнеры на диске или в реестре), и с Рутокен ЭЦП 2.0 (подключённым по USB или в виде smart-card reader).</p>
|
||||
<p>На <a href="/admin/setup">странице «Настройка»</a> в карточке «Криптография» укажите:</p>
|
||||
<ul>
|
||||
<li><strong>Провайдер</strong>: <code>cryptopro</code></li>
|
||||
<li><strong>UDS-сокет</strong>: <code>/run/bj/crypto.sock</code> (для legacy crypto-service на Java — на M2+ переходим на Go-клиент напрямую через PKCS#11)</li>
|
||||
<li><strong>Путь к jcp.jar / PKCS#11</strong>: <code>/opt/cprocsp/lib/amd64/libcppkcs11.so</code></li>
|
||||
<li><strong>Лицензионный ключ</strong>: серийный номер CSP</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>5. Подключение Рутокен ЭЦП 2.0</h2>
|
||||
<p>Подключите Рутокен в USB. Драйверы КриптоПро CSP уже включают поддержку Рутокен:</p>
|
||||
<pre># увидеть подключённые токены
|
||||
/opt/cprocsp/bin/amd64/csptest -card -enum
|
||||
|
||||
# увидеть ключевые контейнеры на токене
|
||||
/opt/cprocsp/bin/amd64/csptest -keyset -enum -unique</pre>
|
||||
<p>Для подписи действий оператора в admin-ui:</p>
|
||||
<ol>
|
||||
<li>Запросить сертификат на физлицо у УЦ (через личный кабинет КриптоПро или через АРМ оператора УЦ).</li>
|
||||
<li>Записать сертификат и контейнер на Рутокен.</li>
|
||||
<li>На <a href="/admin/setup">странице «Настройка»</a> в карточке «Криптография» выбрать провайдер <code>cryptopro</code> и указать слот Рутокен.</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>6. Импорт сертификата</h2>
|
||||
<pre># сертификат корневого УЦ (если ещё нет в системе)
|
||||
/opt/cprocsp/bin/amd64/certmgr -inst -store mroot -file /path/to/root-ca.cer
|
||||
|
||||
# сертификат подписанта (контейнер на токене)
|
||||
/opt/cprocsp/bin/amd64/certmgr -inst -store uMy -cont '\\.\HDIMAGE\my-keys' \
|
||||
-file /path/to/operator.cer
|
||||
|
||||
# проверить установленные сертификаты
|
||||
/opt/cprocsp/bin/amd64/certmgr -list -store uMy</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>7. Тестирование подписи</h2>
|
||||
<p>Через CLI КриптоПро (быстрая проверка что криптография работает):</p>
|
||||
<pre># подписать произвольный файл
|
||||
/opt/cprocsp/bin/amd64/cryptcp -signf -dn 'CN=Иванов И.И.' \
|
||||
-det -strict /tmp/test.txt
|
||||
|
||||
# проверить подпись
|
||||
/opt/cprocsp/bin/amd64/cryptcp -vsignf -det /tmp/test.txt /tmp/test.txt.sgn</pre>
|
||||
<p>Через нашу систему — раздел <a href="/admin/setup">Настройка</a> → кнопка «Запустить тестовую заявку». На странице «Заявка» появится результат и расшифровка проверки подписи.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>8. Поддержка</h2>
|
||||
<ul>
|
||||
<li>Документация КриптоПро: <code>www.cryptopro.ru/products/csp</code></li>
|
||||
<li>Установка на РЕД ОС: <code>www.cryptopro.ru/forum2/default.aspx?g=topics&f=43</code></li>
|
||||
<li>Технические вопросы: <code>support@cryptopro.ru</code></li>
|
||||
<li>Рутокен: <code>dev.rutoken.ru/display/PUB/Rutoken+EDS</code></li>
|
||||
</ul>
|
||||
<p class="muted">При проблемах с лицензией сначала проверьте <code>cpconfig -license -view</code> — лицензия должна быть валидна и не просрочена. Срок действия КриптоПро лицензии — обычно 1 год.</p>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,126 @@
|
||||
{{define "content"}}
|
||||
<p style="margin-bottom:16px"><a href="/admin/help">← все инструкции</a></p>
|
||||
|
||||
<div class="card">
|
||||
<h2>База данных</h2>
|
||||
<p class="muted">PostgreSQL 16 (или PostgreSQL Pro Certified). Хранит сделки, журнал событий, справочники и данные, поступающие из внешних систем через ETL.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>1. Подключение</h2>
|
||||
<p>DSN указывается в разделе <a href="/admin/setup">Настройка → PostgreSQL</a>. Формат:</p>
|
||||
<pre>postgres://USER:PASSWORD@HOST:PORT/DBNAME?sslmode=disable</pre>
|
||||
<p>Локальный дев-стенд:</p>
|
||||
<pre>postgres://bj:bj_dev@127.0.0.1:5432/bj?sslmode=disable</pre>
|
||||
<p class="muted">При сохранении выполняется <code>pgx.Connect</code> и <code>Ping</code>. Если БД недоступна, форма покажет ошибку.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>2. Схемы</h2>
|
||||
<table>
|
||||
<thead><tr><th>Схема</th><th>Назначение</th><th>Кто пишет</th><th>Кто читает</th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>fansy_staging</code></td>
|
||||
<td>Промежуточные таблицы для ETL Fansy</td>
|
||||
<td>Команда Fansy (роль <code>fansy_etl</code>)</td>
|
||||
<td>Наша процедура перелива в <code>fansy</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>fansy</code></td>
|
||||
<td>Рабочие данные: клиенты, документы, ИИС, депо-счета, портфели, справочники ЦБ и участников</td>
|
||||
<td>Наша процедура перелива (после валидации)</td>
|
||||
<td>Наша система (роль <code>bj_reader</code>): m2m-core при формировании заявок</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>m2m_core</code></td>
|
||||
<td>Сделки M2M, журнал событий FSM</td>
|
||||
<td>bj-server</td>
|
||||
<td>bj-server, admin-ui</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>3. Что подгружается из внешних систем</h2>
|
||||
<p>Команда Fansy через инкрементный <strong>UPSERT в staging-таблицы</strong>:</p>
|
||||
<table>
|
||||
<thead><tr><th>Таблица staging</th><th>SLA свежести</th><th>Что в ней</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>clients</code></td><td>≤ 5 минут</td><td>Анкеты инвесторов (ФИО, дата рождения, ИНН)</td></tr>
|
||||
<tr><td><code>client_documents</code></td><td>≤ 5 минут</td><td>Документы (паспорт, ИНН и др.)</td></tr>
|
||||
<tr><td><code>iia_contracts</code></td><td>≤ 5 минут</td><td>Договоры ИИС (тип T12/T03, номер, дата, ИНН брокера)</td></tr>
|
||||
<tr><td><code>depo_accounts</code></td><td>≤ 5 минут</td><td>Депо-счета и разделы у разных депозитариев</td></tr>
|
||||
<tr><td><code>portfolios</code></td><td>≤ 1 минута</td><td>Остатки ЦБ (целое/дробное количество, статус обособления)</td></tr>
|
||||
<tr><td><code>securities</code> / <code>participants</code></td><td>раз в сутки</td><td>Справочники ЦБ и участников MOST</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="muted" style="margin-top:8px">Полный data-dictionary: <code>docs/fansy-contract/v1/data-dictionary.md</code>. Требования к ETL: <code>docs/fansy-contract/v1/etl-requirements.md</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>4. Что пишет сама система</h2>
|
||||
<p>Только в схему <code>m2m_core</code>:</p>
|
||||
<ul>
|
||||
<li><code>deals</code> — корневая запись сделки. Уникальность по <code>guid</code> = идемпотентность приёма заявок.</li>
|
||||
<li><code>deal_events</code> — журнал FSM-событий (event sourcing).</li>
|
||||
</ul>
|
||||
<p>Старт сделки происходит при <code>POST /api/v1/back_office/claims/</code>. FSM проходит этапы:</p>
|
||||
<pre>draft → validated → submitted_to_nsd → awaiting_decision →
|
||||
confirmed → awaiting_sub16 → done
|
||||
↘ rejected
|
||||
↘ timed_out
|
||||
↘ manual_approval</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>5. Учётные записи и роли</h2>
|
||||
<table>
|
||||
<thead><tr><th>Роль</th><th>Права</th><th>Создаёт</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>fansy_etl</code></td><td>SELECT/INSERT/UPDATE на <code>fansy_staging.*</code></td><td>миграция <code>000__roles.sql</code></td></tr>
|
||||
<tr><td><code>bj_reader</code></td><td>SELECT на <code>fansy.*</code></td><td>миграция <code>000__roles.sql</code></td></tr>
|
||||
<tr><td><code>bj_migrator</code></td><td>Владелец схем, DDL-права</td><td>миграция <code>000__roles.sql</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="muted">Пароли проставляются администратором БД через <code>ALTER ROLE</code>, в репозиторий не попадают.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>6. Накатывание миграций</h2>
|
||||
<p>Файлы лежат в <code>migrations/fansy-store/</code> и <code>migrations/m2m-core/</code>. Применить локально:</p>
|
||||
<pre>cd /home/fontvielle/Bridge-and-Join-s
|
||||
for f in migrations/fansy-store/*.sql migrations/m2m-core/*.sql; do
|
||||
podman exec -i bj-postgres psql -U bj -d bj -v ON_ERROR_STOP=1 < "$f"
|
||||
done</pre>
|
||||
<p>Порядок:</p>
|
||||
<ol>
|
||||
<li><code>fansy-store/000__roles.sql</code> — роли</li>
|
||||
<li><code>fansy-store/001__schemas.sql</code> — схемы и гранты</li>
|
||||
<li><code>fansy-store/002__working.sql</code> — рабочая схема</li>
|
||||
<li><code>fansy-store/003__staging.sql</code> — staging</li>
|
||||
<li><code>fansy-store/004__seed_participants.sql</code> — справочник участников (НРД, БКС, Ренессанс, Альфа-Банк)</li>
|
||||
<li><code>m2m-core/001__deals.sql</code> — сделки M2M</li>
|
||||
<li><code>m2m-core/002__stages.sql</code> — jsonb-колонка истории FSM</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>7. Полезные запросы</h2>
|
||||
<pre>-- Состояние сделок за последний час
|
||||
SELECT state, count(*) FROM m2m_core.deals
|
||||
WHERE created_at > now() - interval '1 hour'
|
||||
GROUP BY state;
|
||||
|
||||
-- Журнал событий по сделке
|
||||
SELECT created_at, type, actor, payload
|
||||
FROM m2m_core.deal_events
|
||||
WHERE deal_id = '...'
|
||||
ORDER BY created_at;
|
||||
|
||||
-- Свежесть данных Fansy
|
||||
SELECT 'portfolios' AS t, max(loaded_at) FROM fansy_staging.portfolios
|
||||
UNION ALL SELECT 'clients', max(loaded_at) FROM fansy_staging.clients;</pre>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,93 @@
|
||||
{{define "content"}}
|
||||
<p style="margin-bottom:16px"><a href="/admin/help">← все инструкции</a></p>
|
||||
|
||||
<div class="card">
|
||||
<h2>API личного кабинета (ESIA Finance V1)</h2>
|
||||
<p class="muted">Bridge-and-Join-s реализует контракт ESIA Finance V1 на стороне back-office. ЛК клиента отправляет нам заявку, мы возвращаем подтверждение и потом колбэк со статусом. Полная спецификация: <code>docs/lk-contract/v1/openapi.yaml</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>1. Аутентификация</h2>
|
||||
<p>HTTP <strong>Basic</strong>. Учётные записи и пароли согласуются с командой ЛК.</p>
|
||||
<pre>curl -u "lk-user:lk-password" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://10.10.10.22:8080/api/v1/back_office/claims/</pre>
|
||||
<p class="muted">На M2 (дев-стенд) аутентификация отключена; включится на M3 — параллельно с подключением реального ЛК.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>2. Создание заявки M2M</h2>
|
||||
<p><code>POST /api/v1/back_office/claims/</code></p>
|
||||
<p>Тело — JSON, кодировка UTF-8. Минимально нужно: анкета инвестора, ИНН передающего и принимающего депозитария, информация о стоимости, массив ценных бумаг с количеством и счетами, подписанный XML заявления (base64).</p>
|
||||
<pre>curl -X POST http://10.10.10.22:8080/api/v1/back_office/claims/ \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @docs/lk-contract/v1/examples/claim-request.json</pre>
|
||||
<p>Ответ <code>201 Created</code>:</p>
|
||||
<pre>{
|
||||
"id": "c02a1d5e-c2af-4799-bab4-953f133c5133",
|
||||
"status": "submitted_to_nsd",
|
||||
"created_at": "2026-03-02T14:30:45Z",
|
||||
"success": true
|
||||
}</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>3. Получение заявки и её статуса</h2>
|
||||
<p><code>GET /api/v1/back_office/claims/{id}</code></p>
|
||||
<pre>curl http://10.10.10.22:8080/api/v1/back_office/claims/c02a1d5e-c2af-4799-bab4-953f133c5133</pre>
|
||||
<p>Возвращает полную карточку с историей FSM, ответом НРД и решением принимающей стороны (когда оно пришло).</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>4. Список заявок</h2>
|
||||
<p><code>GET /api/v1/back_office/claims</code> с query-фильтрами: <code>status</code>, <code>investor_id</code>, <code>created_from</code>, <code>created_to</code>, <code>limit</code>, <code>offset</code>.</p>
|
||||
<pre>curl "http://10.10.10.22:8080/api/v1/back_office/claims?status=confirmed&limit=20"</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>5. Callback статуса (мы → ЛК)</h2>
|
||||
<p>Когда сделка меняет статус (подтверждена принимающей стороной, отклонена, или произошёл таймаут), bj-server делает <code>PATCH {LK_BASE}/api/v1/back_office/claims/{id}</code>:</p>
|
||||
<pre>{
|
||||
"claim_id": "c02a1d5e-c2af-4799-bab4-953f133c5133",
|
||||
"new_status": "confirmed",
|
||||
"updated_at": "2026-03-02T14:38:12Z",
|
||||
"nsd_response": {
|
||||
"guid": "...",
|
||||
"status_code": "INFO",
|
||||
"responses": [{"reference_id": "M2M2026...", "code": "01", "text": "..."}]
|
||||
}
|
||||
}</pre>
|
||||
<p>Адрес ЛК указывается в <a href="/admin/setup">Настройка → Callback в ЛК</a> или через переменную <code>BJ_LK_CALLBACK_URL</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>6. Формат ошибок</h2>
|
||||
<p>Любая ошибка возвращается в формате, идентичном ESIA Finance V1:</p>
|
||||
<pre>{
|
||||
"error": true,
|
||||
"status": 422,
|
||||
"code": "invalid_signature",
|
||||
"title": "Подпись заявления не прошла проверку",
|
||||
"meta": {
|
||||
"message": "Сертификат подписанта недействителен или цепочка доверия не построена.",
|
||||
"errors": [{"field": "signed_document", "message": "..."}]
|
||||
}
|
||||
}</pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>7. Эмулятор ЛК для тестов</h2>
|
||||
<p>На дев-стенде доступен <strong>lk-emulator</strong> на порту 8083 — имитация ЛК. Он сам регистрирует свой URL в bj-server как callback-приёмник.</p>
|
||||
<ul>
|
||||
<li><code>http://10.10.10.22:8083/</code> — журнал моих заявок (автообновление 3 сек)</li>
|
||||
<li><code>http://10.10.10.22:8083/new</code> — форма «подать заявку» с предустановленными инвесторами из seed-данных</li>
|
||||
<li>При запуске реального ЛК эмулятор остаётся как QA-инструмент</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>8. Подписание заявления</h2>
|
||||
<p>ЛК должен подписать заявление XMLDSig (ГОСТ или RSA) и положить в поле <code>signed_document</code> (base64). Мы проверяем подпись через crypto-service — см. <a href="/admin/help/cryptopro">инструкцию по КриптоПро</a>.</p>
|
||||
<p class="muted">На M2 проверка подписи отключена (stub). На M3-M4 включится после подключения СКЗИ.</p>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,76 @@
|
||||
{{define "content"}}
|
||||
<p style="margin-bottom:16px"><a href="/admin/help">← все инструкции</a></p>
|
||||
|
||||
<div class="card">
|
||||
<h2>Внешние системы</h2>
|
||||
<p class="muted">Как Bridge-and-Join-s взаимодействует с тремя главными внешними сторонами: НРД (через ИШ), команда Fansy (ETL в БД), уведомления операторам.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>1. Интеграционный шлюз НРД (ИШ)</h2>
|
||||
<p>Основной канал отправки M2M-сообщений в НРД. ИШ сам подписывает пакеты ЭДО, нам криптография в этом канале не нужна.</p>
|
||||
<p><strong>Профили</strong> (см. <a href="/admin/setup">Настройка → Интеграционный шлюз НРД</a>):</p>
|
||||
<table>
|
||||
<thead><tr><th>Профиль</th><th>Среда</th><th>Криптография</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>guest-gost</code></td><td>Гостевой контур (без проверок)</td><td>ГОСТ Р 34.10-2012</td></tr>
|
||||
<tr><td><code>guest-rsa</code></td><td>Гостевой контур</td><td>RSA</td></tr>
|
||||
<tr><td><code>test3-gost</code></td><td>Тестовый контур TEST3</td><td>ГОСТ</td></tr>
|
||||
<tr><td><code>test3-rsa</code></td><td>TEST3</td><td>RSA</td></tr>
|
||||
<tr><td><code>prod-gost</code></td><td>Продуктивный</td><td>ГОСТ</td></tr>
|
||||
<tr><td><code>prod-rsa</code></td><td>Продуктивный</td><td>RSA</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Что указать в Настройка → ИШ:</strong></p>
|
||||
<ul>
|
||||
<li>Профиль (например, <code>test3-gost</code>)</li>
|
||||
<li>URL ИШ — обычно <code>http://localhost:8080</code> если ИШ установлен на той же ВМ</li>
|
||||
<li>Ключевой контейнер — имя на стороне ИШ, например <code>TEST3_GOST_CONTAINER</code></li>
|
||||
</ul>
|
||||
<p class="muted">Без настроенного ИШ система работает в <strong>mock-режиме</strong>: bj-server эмитирует синтетический Decision через 3 секунды для каждой заявки. Это удобно для дев-демо и не требует подключения к НРД.</p>
|
||||
<p><strong>Документация по подключению</strong>: <code>DOC/instr_podkl_stend_v3.pdf</code>, <code>DOC/Ссылки для доступа в тестовые контуры.pdf</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>2. Команда Fansy (ETL в БД)</h2>
|
||||
<p>Команда Fansy на своей стороне настраивает ETL, который пишет в схему <code>fansy_staging.*</code> нашей БД. Мы переливаем оттуда в <code>fansy.*</code> после валидации.</p>
|
||||
<p><strong>Что от вас как заказчика нужно:</strong></p>
|
||||
<ol>
|
||||
<li>Передать команде Fansy ссылку на каталог <code>docs/fansy-contract/v1/</code> (тег <code>fansy-contract-v1</code>).</li>
|
||||
<li>Согласовать SLA свежести и расписание (по умолчанию — портфели за 1 минуту, остальное за 5 минут, справочники раз в сутки).</li>
|
||||
<li>Завести в БД учётную запись с ролью <code>fansy_etl</code> и передать команде Fansy. Пароль выдать через защищённый канал.</li>
|
||||
<li>Прописать IP/подсеть Fansy в <code>pg_hba.conf</code> на стороне PostgreSQL (только TLS, <code>sslmode=verify-full</code>).</li>
|
||||
</ol>
|
||||
<p>Полный контракт: <code>docs/fansy-contract/v1/etl-requirements.md</code>. Семантика полей: <code>docs/fansy-contract/v1/data-dictionary.md</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>3. Уведомления операторам</h2>
|
||||
<p>В M3-M4 будет раздел <strong>Настройка → Уведомления</strong>. Архитектура — провайдеры-плагины с единым интерфейсом <code>Notifier { Send(ctx, recipient, template, data) }</code>:</p>
|
||||
<table>
|
||||
<thead><tr><th>Провайдер</th><th>Назначение</th><th>Что вводить</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>SMTP</td><td>E-mail (внутренний или внешний сервер)</td><td>хост, порт, логин/пароль, from-адрес</td></tr>
|
||||
<tr><td>Yandex Messenger (Yandex 360)</td><td>Корпоративный мессенджер. У заказчика уже есть готовый бот — дотягиваем его</td><td>API-token, webhook, chat-id / user-id</td></tr>
|
||||
<tr><td>Telegram</td><td>Опционально для отдельных операторов</td><td>bot-token, chat-id</td></tr>
|
||||
<tr><td>Mattermost / Rocket.Chat</td><td>Корпоративные мессенджеры (если используются)</td><td>webhook URL</td></tr>
|
||||
<tr><td>WebSocket в admin-ui</td><td>Мгновенный push если оператор открыл вкладку</td><td>встроено, без настроек</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Логика маршрутизации:</strong> критичный этап (ручное согласование, >80% SLA, отказ НРД) → параллельно e-mail + Messenger + WS-push. Обычные события — только e-mail. Маршрутизация по ролям настраивается в UI.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>4. Контакты команд</h2>
|
||||
<table>
|
||||
<thead><tr><th>Внешняя сторона</th><th>Что согласовать</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>НРД (Национальный расчётный депозитарий)</td><td>Тестовые сертификаты GUEST/TEST3, дистрибутив ИШ, доступ к личному кабинету УЦ НРД</td></tr>
|
||||
<tr><td>Команда ЛК (ESIA Finance)</td><td>Базовый URL ЛК, Basic-auth учётные данные, очерёдность подключения (сначала эмулятор, потом реальный ЛК)</td></tr>
|
||||
<tr><td>Команда Fansy</td><td>Контракт <code>docs/fansy-contract/v1/</code>, SLA, окна обслуживания, IP-allowlist</td></tr>
|
||||
<tr><td>КриптоПро</td><td>Серийный номер лицензии CSP, актуальный дистрибутив, поддержка <code>support@cryptopro.ru</code></td></tr>
|
||||
<tr><td>Брокеры-контрагенты MOST</td><td>БКС (ИНН 5406121446), Ренессанс (7709258228), Альфа-Банк (7728168971) — уже в seed</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -44,7 +44,7 @@
|
||||
<td><code>{{slice .ID 0 8}}</code></td>
|
||||
<td>{{.Investor.LastName}} {{slice .Investor.FirstName 0 1}}.</td>
|
||||
<td>{{len .Securities}}</td>
|
||||
<td><span class="badge {{.Status}}">{{.Status}}</span></td>
|
||||
<td><span class="badge {{.Status}}">{{ruState .Status}}</span></td>
|
||||
<td><a href="/admin/claims/{{.ID}}">открыть →</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user