feat(billing): PaymentProvider + Mock, self-service пополнение баланса
Шаг 0.13 плана production-готовности: - интерфейс PaymentProvider (createPayment/verifyWebhook/getPaymentStatus) - MockPaymentProvider с настоящим webhook (sha256-подпись, идемпотентность) - applySucceededPayment: транзакция с guard, credit, авто-снятие billingBlocked - роуты payments + confirm-test (только mock) + публичный webhook - Billing.tsx: Пополнить/Подтвердить (тест), фикс setLocation в рендере - миграция 0080 billing_payments, 13 новых тестов (78/78)
This commit is contained in:
22
migrations/0080_billing_payments.sql
Normal file
22
migrations/0080_billing_payments.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
-- Шаг 0.13 плана production-готовности: платежи самообслуживания биллинга.
|
||||
-- Пополнение баланса админом организации через платёжного провайдера (сейчас — mock).
|
||||
-- Без RLS: запись — только серверные роуты (auth + billing.manage) и webhook провайдера,
|
||||
-- чтение — только через роуты с явным фильтром organization_id.
|
||||
CREATE TABLE IF NOT EXISTS billing_payments (
|
||||
id SERIAL PRIMARY KEY,
|
||||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
provider VARCHAR(30) NOT NULL,
|
||||
external_id VARCHAR(255) NOT NULL,
|
||||
amount NUMERIC(10,2) NOT NULL,
|
||||
currency VARCHAR(10) NOT NULL DEFAULT 'RUB',
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
idempotency_key VARCHAR(255) NOT NULL,
|
||||
metadata JSONB,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE (external_id),
|
||||
UNIQUE (idempotency_key)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS billing_payments_org_status_idx
|
||||
ON billing_payments (organization_id, status);
|
||||
Reference in New Issue
Block a user