feat(tradein/payments): схема БД, конфиг и kill-switch платёжного контура #2732

Merged
lekss361 merged 5 commits from feat/tradein-payments-schema into main 2026-08-06 16:33:28 +00:00
2 changed files with 72 additions and 32 deletions
Showing only changes of commit 95ed9c7811 - Show all commits

View file

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

View file

@ -230,4 +230,4 @@
# Тем самым снято отложенное условие из прошлой редакции: 187/188 (веб-чат # Тем самым снято отложенное условие из прошлой редакции: 187/188 (веб-чат
# поддержки, #2532/#2533) откладывались до подтверждения, что они осели на # поддержки, #2532/#2533) откладывались до подтверждения, что они осели на
# проде в финальном виде. Они в _schema_migrations — условие выполнено. # проде в финальном виде. Они в _schema_migrations — условие выполнено.
232_payments.sql 233_payments.sql