Мастер, QUIK: короткое письмо в ARQA с внешним адресом, памятка администратору, понятный выбор работы с QUIK
- Письмо в ARQA: организация просит подключить модуль неторговых поручений, выдать логин и пароль и разрешить подключение с нашего внешнего адреса — о bj и внутреннем устройстве ни слова. Внешний адрес bj узнаёт у сервера лицензий (GET /v1/ip, раз в час); пометка — убедиться, что адрес постоянный. - Под письмом — «Памятка администратору QUIK» (классы, логин InstrEu, справочник, перезапуск модуля) со ссылкой на подробную инструкцию. - Вместо свёрнутого «Автоматический цикл M2M — выключен · настроить» и справочника под раскрытием: после проверки подключения — «Как bj работает с QUIK»: «Только сверка» или «Автоматически» (+ торговый счёт), сохраняется сразу; справочник — строкой состояния с напоминанием о перезапуске. До проверки — одна строка. Тонкая настройка — в «Настройка → QUIK», мастер её не трогает. - Проверка МНП: ошибка сертификата (x509, «doesn't contain any IP SANs») — подсказка включить «Доверять сертификату сервера», «Дополнительно» раскрывается. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -17,6 +17,7 @@ func (h *setupHandlers) registerQuik(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/admin/setup/quik/test", h.testQuik)
|
||||
mux.HandleFunc("/admin/quik", h.quikInstructions)
|
||||
mux.HandleFunc("/admin/setup/quik/cycle", h.saveQuikCycle)
|
||||
mux.HandleFunc("/admin/setup/quik/mode", h.saveQuikMode)
|
||||
}
|
||||
|
||||
// quikInstructions — GET /admin/quik. Поручения M2M из БД МНП QUIK.
|
||||
@@ -122,6 +123,43 @@ func (h *setupHandlers) saveQuikCycle(w http.ResponseWriter, r *http.Request) {
|
||||
setupFlash(w, r, "QUIK МНП: цикл M2M сохранён — "+mode)
|
||||
}
|
||||
|
||||
// saveQuikMode — POST /admin/setup/quik/mode (мастер): как bj работает с QUIK — одним выбором вместо набора
|
||||
// флажков. check — только сверка (в МНП bj не пишет, поручения вводят сотрудники); auto — bj ведёт поручения
|
||||
// сам: исходящие (блокировка, списание или снятие) и входящие (зачисление). Тонкая настройка (инструменты,
|
||||
// коды клиентов, поручения из терминала, имитация) — в «Настройке», здесь не трогается. Экран сохраняет
|
||||
// выбор сразу (X-BJ-Ajax — ответ строкой), без JavaScript — обычной формой.
|
||||
func (h *setupHandlers) saveQuikMode(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireAdvanced(w, r) {
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "method", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
s := h.rc.Snapshot().Quik
|
||||
auto := r.FormValue("mode") == "auto"
|
||||
s.WritesEnabled, s.AutoOut, s.AutoIn = auto, auto, auto
|
||||
if r.PostForm.Has("account") {
|
||||
s.Account = strings.TrimSpace(r.FormValue("account"))
|
||||
}
|
||||
msg := "только сверка — в QUIK bj ничего не пишет"
|
||||
if auto {
|
||||
msg = "автоматически — bj ведёт поручения в QUIK сам"
|
||||
if s.Account == "" {
|
||||
msg += "; укажите торговый счёт"
|
||||
}
|
||||
}
|
||||
if err := h.rc.UpdateQuik(s); err != nil {
|
||||
msg = "не сохранилось: " + err.Error()
|
||||
}
|
||||
if r.Header.Get("X-BJ-Ajax") != "" {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
_, _ = w.Write([]byte(msg))
|
||||
return
|
||||
}
|
||||
setupFlash(w, r, "QUIK: "+msg)
|
||||
}
|
||||
|
||||
func onOff(b bool) string {
|
||||
if b {
|
||||
return "авто"
|
||||
@@ -168,6 +206,21 @@ func (h *setupHandlers) saveQuik(w http.ResponseWriter, r *http.Request) {
|
||||
setupFlash(w, r, fmt.Sprintf("QUIK МНП: настройки сохранены (%s:%d, логин %s)", s.Server, s.Port, s.User))
|
||||
}
|
||||
|
||||
// quikCertHint — что делать, когда сервер МНП не прошёл проверку сертификата: у QUIK сертификат обычно свой
|
||||
// (самоподписанный или на имя сервера, а подключаемся по IP).
|
||||
const quikCertHint = "сертификат сервера МНП выписан не на этот адрес или самоподписанный (так у QUIK обычно и бывает). Включите «Доверять сертификату сервера» в «Дополнительно: база и шифрование» и проверьте ещё раз — соединение останется зашифрованным."
|
||||
|
||||
// quikCertError — подключение не прошло из-за проверки сертификата сервера (не из-за сети или логина).
|
||||
func quikCertError(err error) bool {
|
||||
m := strings.ToLower(err.Error())
|
||||
return strings.Contains(m, "x509:") || strings.Contains(m, "failed to verify certificate") || strings.Contains(m, "certificate signed by unknown authority")
|
||||
}
|
||||
|
||||
// quikNeedsTrust — последняя проверка упала на сертификате, а доверие выключено: раскрыть «Дополнительно».
|
||||
func quikNeedsTrust(s QuikMNPSettings) bool {
|
||||
return !s.Verified && !s.Trust && strings.Contains(s.LastReport, "Что сделать: сертификат")
|
||||
}
|
||||
|
||||
// testQuik — POST /admin/setup/quik/test. Тест-подключение (только чтение).
|
||||
// Формирует ПОЛНЫЙ отчёт (параметры + ответ сервера) для копирования коллегам.
|
||||
func (h *setupHandlers) testQuik(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -195,10 +248,18 @@ func (h *setupHandlers) testQuik(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(&b, "РЕЗУЛЬТАТ: ОШИБКА ПОДКЛЮЧЕНИЯ\n\n")
|
||||
b.WriteString(quikErrorDetail(err))
|
||||
cert := quikCertError(err) && !s.Trust
|
||||
if cert {
|
||||
b.WriteString("\n\nЧто сделать: " + quikCertHint)
|
||||
}
|
||||
s.Verified = false
|
||||
s.LastReport = b.String()
|
||||
s.LastAt = now.UTC()
|
||||
_ = h.rc.UpdateQuik(s)
|
||||
if cert {
|
||||
setupFlash(w, r, "QUIK МНП: "+quikCertHint)
|
||||
return
|
||||
}
|
||||
setupFlash(w, r, "QUIK МНП: подключение не удалось — полный ответ сервера ниже (можно скопировать для коллег)")
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user