diff --git a/tradein-mvp/backend/data/sql/232_payments.sql b/tradein-mvp/backend/data/sql/233_payments.sql similarity index 73% rename from tradein-mvp/backend/data/sql/232_payments.sql rename to tradein-mvp/backend/data/sql/233_payments.sql index affc6882..99dfeca9 100644 --- a/tradein-mvp/backend/data/sql/232_payments.sql +++ b/tradein-mvp/backend/data/sql/233_payments.sql @@ -1,11 +1,16 @@ --- 232_payments.sql +-- 233_payments.sql -- Платёжный контур МЕРЫ (Т-Банк интернет-эквайринг) — схема БД, PR-B из серии -- A..F (см. корень репо `mera-tbank-acquiring-recon.md`, §9 «Разбивка на PR»). -- Ни разу не применялась на проде (см. `_manifest_applied.txt`) — правится на --- месте по итогам review (статус HOLD), без ребейза номера. Переименована из --- 228_payments.sql в 232_payments.sql (git mv, история сохранена): номер 228 --- заняли 228_scrape_proxies_browser_health.sql, 230 — 230_house_merge_log.sql --- (влились в main, пока шло ревью); 229 и 231 параллельно занимает PR #2547. +-- месте по итогам review (статус HOLD), без ребейза номера. Дважды +-- переименована (git mv, история сохранена): 228 → 232 → 233. Номер 228 +-- заняли 228_scrape_proxies_browser_health.sql и 230_house_merge_log.sql +-- (влились в main); 229 и 231 занимает открытый PR #2547; 232 занял открытый +-- PR #2742 (`232_listings_observation_time_meaning.sql`). Урок: сверять номер +-- нужно не только по `forgejo/main`, но и по ВСЕМ открытым PR-веткам — ни один +-- из этих файлов сам себя в `_manifest_applied.txt` не пишет (мы пишем), из-за +-- чего коллизия обнаруживается только тестом `test_new_files_do_not_reuse_prefix` +-- уже после того, как чей-то PR смержен первым. -- -- ── WHY ────────────────────────────────────────────────────────────────────── -- Этот PR — ТОЛЬКО схема + конфиг + kill-switch (`PAYMENTS_ENABLED=false` в @@ -49,32 +54,62 @@ -- DO UPDATE). Применено к обоим дедуп-ключам ниже. -- -- ── СТАТУСЫ T-BANK (payments.status CHECK) ────────────────────────────────── --- Список сверен с публичным Status-enum T-Bank Acquiring API. Источник --- developer.tbank.ru рендерит enum клиентским JS (правая панель схемы ответа --- динамически подгружается) — прямого текстового доступа к разделу GetState --- не получено; сверка выполнена по независимому активно поддерживаемому --- Go-клиенту (github.com/nikita-vanyasin/tinkoff, файл status.go), который --- явно комментирует каждый статус. Изменения относительно первой версии: --- - УБРАНЫ 'AUTHORIZED_AND_CHARGED' и 'RECEIPT_REGISTERED' — не найдены ни --- в одном сверенном источнике; RECEIPT_REGISTERED похоже на статус --- отдельного объекта «чек» (SendClosingReceipt), не платежа. --- - ДОБАВЛЕНЫ '3DS_CHECKING' и '3DS_CHECKED' — подтверждены сверкой. --- - НЕ добавлены 'ATTEMPTS_EXPIRED' и 'PAY_CHECKING' (гипотеза из ревью) — --- не нашлись ни в одном источнике, которым удалось свериться; если реально --- существуют — расширить CHECK отдельной миграцией по факту документа. --- - 'PARTIAL_REVERSED' оставлен: та же сверка его подтверждает (реально --- существующий статус частичной отмены холда), а не «оставлен из --- осторожности», как было сформулировано раньше. --- - 'PREAUTHORIZING' оставлен как есть (не проверялся под вопрос ревью): --- тот же Go-клиент помечает его комментарием "deprecated / removed from --- API", но это не запрошенная часть проверки — трогать не стал, инертное --- значение в CHECK безвредно, если банк его больше не шлёт. --- Контракт для PR-D: если банк присылает статус вне списка ниже, обработчик --- нотификаций обязан писать в payments.status значение 'UNKNOWN' (не поднимать --- исключение, не терять запись) — сырое тело в любом случае лежит целиком в --- payment_notifications.body. INSERT/UPDATE payments с любым другим --- незнакомым значением упадёт на CHECK — это специально: тихое искажение --- статуса хуже, чем громкий сбой одной записи. +-- Источник истины — официальная OpenAPI-спека: +-- https://developer.tbank.ru/schemas/eacq/openapi.yaml (OpenAPI 3.0.2, v1.24), +-- схема `Confirm-2`, 24 значения. На странице /eacq/intro/developer/openapi +-- прямо сказано: при расхождении прозы и спеки приоритет у спеки — поэтому +-- ссылка на спеку, а не на человекочитаемые доки. +-- +-- ВАЖНО про GetState/CheckOrder (ручки, которыми реконсиляция PR-E читает +-- статус): в спеке их поле `Status` объявлено СВОБОДНОЙ строкой +-- (`maxLength: 20`, БЕЗ enum). То есть на ручках, которыми фактически питается +-- реконсиляция, банк словарь значений не фиксирует контрактно — наш CHECK +-- здесь строже, чем контракт поставщика. Это осознанный выбор (закрытый +-- список читается и валидируется проще, чем произвольная строка), а не +-- недосмотр; следующий читатель должен видеть, что этот CHECK может однажды +-- отвергнуть легитимный, но недокументированный `Confirm-2`-строкой статус — +-- см. контракт 'UNKNOWN' ниже. +-- +-- Сверка по `Confirm-2` относительно первой версии миграции: +-- - УБРАНЫ 'AUTHORIZED_AND_CHARGED' и 'RECEIPT_REGISTERED' — отсутствуют в +-- `Confirm-2`. Дополнительно у поля `Status` в спеке `maxLength: 20`, а +-- 'AUTHORIZED_AND_CHARGED' — 22 символа: физически не может быть значением +-- этого поля, не только "не найдено", а невозможно по контракту. +-- - ДОБАВЛЕНЫ '3DS_CHECKING' и '3DS_CHECKED' — есть в `Confirm-2`. +-- - НЕ добавлены 'ATTEMPTS_EXPIRED' и 'PAY_CHECKING' — отсутствуют в +-- `Confirm-2`, гипотеза не подтвердилась. +-- - 'PREAUTHORIZING' оставлен и подтверждён: есть в `Confirm-2`. (Ранее +-- редакция ссылалась на комментарий стороннего Go-клиента о том, что этот +-- статус будто бы убран из API — спекой это не подтверждается, комментарий +-- был неточным источником и снят.) +-- - ДОБАВЛЕНЫ пять пропущенных in-flight значений из `Confirm-2`: +-- 'CHECKING', 'CHECKED', 'PROCESSING', 'COMPLETING', 'COMPLETED'. Это +-- ровно те статусы, которые GetState/CheckOrder вернёт по зависшему +-- платежу — их читает реконсиляция (PR-E). Пропуск реального значения — +-- единственное опасное направление ошибки CHECK: не "лишний" статус +-- проскочит, а свой же CHECK отвергнет то, что банк реально прислал. +-- Порядок в списке ниже — по смысловой близости к соседним стадиям +-- (CHECKING/CHECKED рядом с 3DS_CHECKING/3DS_CHECKED, COMPLETING/COMPLETED +-- рядом с CONFIRMED), а не порядок из спеки — `Confirm-2` не гарантирует +-- порядок enum, для CHECK-констрейнта (проверка принадлежности множеству) +-- порядок значения не имеет. +-- - 'PARTIAL_REVERSED' и 'REFUND_FAILED' в `Confirm-2` ОТСУТСТВУЮТ. Оставлены +-- в CHECK как безвредный запас на случай появления в будущей версии API +-- (сам факт лишнего разрешённого значения в CHECK ничего не ломает — в +-- отличие от отсутствующего). Это отличается от предыдущей редакции +-- комментария, которая ошибочно утверждала, что сверка их "подтверждает": +-- не подтверждает, они не найдены в источнике истины. +-- +-- Контракт: если банк присылает статус вне списка ниже, ОБРАБОТЧИК +-- НОТИФИКАЦИЙ И ЗАДАЧА РЕКОНСИЛЯЦИИ (GetState/CheckOrder, PR-E) обязаны +-- писать в payments.status значение 'UNKNOWN' (не поднимать исключение, не +-- терять запись) — сырое тело нотификации в любом случае лежит целиком в +-- payment_notifications.body (у GetState/CheckOrder своего append-only лога +-- нет — если реконсиляция сама не сохранит сырой ответ, факт неизвестного +-- статуса останется только в payments.status='UNKNOWN' и её собственных логах). +-- INSERT/UPDATE payments с любым другим незнакомым значением упадёт на +-- CHECK — это специально: тихое искажение статуса хуже, чем громкий сбой +-- одной записи. -- -- ── payment_entitlements: без кредитно-кошельковой семантики ──────────────── -- Первая версия несла amount/consumed (модель «кредиты/пакеты»). Явно @@ -173,8 +208,13 @@ ALTER TABLE payments 'REJECTED', '3DS_CHECKING', '3DS_CHECKED', + 'CHECKING', + 'CHECKED', + 'PROCESSING', 'CONFIRMING', 'CONFIRMED', + 'COMPLETING', + 'COMPLETED', 'REVERSING', 'PARTIAL_REVERSED', 'REVERSED', diff --git a/tradein-mvp/backend/data/sql/_manifest_applied.txt b/tradein-mvp/backend/data/sql/_manifest_applied.txt index 75c13875..7d71c6d7 100644 --- a/tradein-mvp/backend/data/sql/_manifest_applied.txt +++ b/tradein-mvp/backend/data/sql/_manifest_applied.txt @@ -230,4 +230,4 @@ # Тем самым снято отложенное условие из прошлой редакции: 187/188 (веб-чат # поддержки, #2532/#2533) откладывались до подтверждения, что они осели на # проде в финальном виде. Они в _schema_migrations — условие выполнено. -232_payments.sql +233_payments.sql