Платежі

Чекліст виходу в Production

20 пунктів перевірки перед запуском платіжної системи в production — конфігурація, безпека, моніторинг, логування, юридична готовність.

Чекліст виходу в Production

Від «воно працює локально» до «воно готове для реальних грошей»

Розробники часто недооцінюють різницю між «платіж пройшов у Sandbox» та «система готова до прийому реальних платежів». Перехід у production — це не просто зміна API-ключів. Це комплексна перевірка: технічна, безпекова, операційна та юридична.

Цей чекліст — ваш останній рубіж перед Go-Live.


Блок 1: Конфігурація та середовища

✅ Ключі та секрети

  • Production ключі збережено у Secret Manager / Environment Variables, НЕ у коді або appsettings.json
  • Sandbox ключі видалено або заблоковано в production оточенні
  • IsSandbox = false для production, true для всіх інших оточень
  • Webhook URL оновлено з ngrok → production domain

✅ Environment конфігурація

  • ASPNETCORE_ENVIRONMENT = Production
  • Окремі appsettings.Development.json / appsettings.Production.json
  • Retry policy для HTTP-клієнтів налаштовано (Polly)
  • Timeout для PSP API-запитів: рекомендовано 30 секунд
Program.cs
// Обов'язковий патерн для безпечного отримання секретів у production
builder.Configuration
    .AddEnvironmentVariables()
    .AddUserSecrets<Program>(optional: true); // Тільки для Development!

// Перевірка наявності обов'язкових налаштувань
var liqPayKey = builder.Configuration["LiqPay:PrivateKey"]
    ?? throw new InvalidOperationException(
        "LiqPay:PrivateKey is not configured. " +
        "Set via environment variable or Secret Manager.");

Блок 2: Безпека

PCI DSS Self-Assessment

Пройдіть SAQ відповідного рівня (для більшості — SAQ-A або SAQ-A-EP) та зберігайте результат. Ряд PSP вимагає підтвердження при укладанні договору.

HTTPS обов'язковий

Усі платіжні endpoints повинні працювати виключно через HTTPS. Додайте:

Program.cs
app.UseHttpsRedirection();
app.UseHsts(); // HTTP Strict Transport Security

CSP заголовки

Program.cs
app.Use(async (context, next) =>
{
    context.Response.Headers.Append("Content-Security-Policy",
        "default-src 'self'; " +
        "script-src 'self' https://static.liqpay.ua https://js.stripe.com; " +
        "frame-src https://www.liqpay.ua https://js.stripe.com; " +
        "connect-src 'self' https://api.stripe.com");
    await next();
});

Rate Limiting на платіжних endpoints

Program.cs
builder.Services.AddRateLimiter(opts =>
{
    opts.AddFixedWindowLimiter("payments", o =>
    {
        o.PermitLimit = 10;
        o.Window = TimeSpan.FromMinutes(1);
        o.QueueLimit = 0;
    });
});

// Застосовуємо до платіжних endpoints
group.RequireRateLimiting("payments");

Перевірка підписів webhook налаштована для всіх PSP

Переконайтесь, що верифікація підпису активна для LiqPay (SHA1), Monobank (ECDSA) та Stripe (HMAC-SHA256) у production конфігурації.


Блок 3: Логування та моніторинг

Що потрібно логувати:

Services/PaymentService.cs
// Логуємо бізнес-події (без PII та даних картки)
_logger.LogInformation(
    "Payment {PaymentId} created. Provider: {Provider}, Amount: {Amount} {Currency}",
    payment.Id, payment.Provider, payment.Amount, payment.Currency);

_logger.LogWarning(
    "Payment {PaymentId} failed. ProviderError: {Error}",
    payment.Id, result.ErrorMessage);

// Webhook
_logger.LogInformation(
    "Webhook received from {Provider}: event={EventId}, status={Status}",
    provider, eventId, status);

Що НЕ потрібно логувати:

  • PAN (номер картки) — навіть у замаскованому вигляді без потреби
  • CVV/CVC — ніколи
  • Токени PSP — лише для debugging з рівнем Trace
  • Повний webhook payload — лише з маскуванням чутливих полів

Метрики для моніторингу:

payment_success_rate
gauge
Відсоток успішних транзакцій за останню годину. Алерт якщо < 80%.
payment_failed_count
counter
Кількість відхилених транзакцій. Різкий стрибок → можлива атака або проблема з PSP.
webhook_processing_lag
histogram
Час між отриманням webhook та оновленням статусу. Алерт якщо > 30 секунд.
chargeback_rate
gauge
Відсоток chargebacks від загальної кількості. Критично > 1%.

Блок 4: Надійність та відмовостійкість

Program.cs
// Retry policy для PSP HTTP-клієнтів
builder.Services.AddHttpClient<LiqPayClient>()
    .AddStandardResilienceHandler(config =>
    {
        config.Retry.MaxRetryAttempts = 3;
        config.Retry.Delay = TimeSpan.FromSeconds(1);
        config.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(30);
        config.CircuitBreaker.SamplingDuration = TimeSpan.FromMinutes(1);
    });

Graceful degradation: якщо PSP недоступний, відображайте зрозуміле повідомлення («Платіжний сервіс тимчасово недоступний. Спробуйте через кілька хвилин.»), а не generic 500.


Блок 5: Юридична готовність

📄 Договір з PSP

Переконайтесь, що ви уклали офіційний договір з PSP (LiqPay/Monobank/Stripe). Sandbox не потребує договору, але production — обов'язково. Включаючи: ставки комісій, терміни виплат, умови припинення.

📋 Публічна оферта

На сайті має бути розміщена публічна оферта з описом: умови оплати, умови повернення (відповідно до Закону про захист прав споживачів), строки доставки (для товарів).

🔒 Політика конфіденційності

Політика конфіденційності має описувати: які дані збираються, як зберігаються, як передаються PSP, права користувача. Відповідно до GDPR (для EU клієнтів) та Закону про захист персональних даних України.

🧾 Фіскалізація

Для B2C платежів в Україні — обов'язкова видача фіскального чека (відповідно до Закону №1017-IX про ПРРО). LiqPay та деякі PSP мають вбудовану фіскалізацію. Уточніть у PSP.

20-пунктовий Go-Live Checklist

Технічна готовність
□ 1.  Production API ключі налаштовані через env variables
□ 2.  Sandbox флаг IsSandbox = false у production
□ 3.  HTTPS + HSTS налаштовано
□ 4.  Webhook URL оновлено до production домену
□ 5.  Webhook підписи верифікуються для всіх PSP
□ 6.  Ідемпотентна обробка webhook реалізована
□ 7.  Rate limiting на платіжних endpoints
□ 8.  Retry policy для PSP HTTP-клієнтів (Polly)
□ 9.  Graceful error handling (ProblemDetails, user-friendly messages)
□ 10. Таймаути на всіх HTTP-запитах до PSP (≤30 секунд)

Безпека
□ 11. PAN, CVV ніде не зберігаються у вашій БД
□ 12. Логи маскують чутливі дані
□ 13. CSP headers налаштовано
□ 14. Пройдено SAQ відповідного рівня

Моніторинг
□ 15. Алерти на payment_success_rate < 80%
□ 16. Алерти на webhook_processing_lag > 30s
□ 17. Логи платіжних подій збираються (ELK/Sentry/Datadog)

Операційна готовність
□ 18. Задокументована процедура повернення коштів (для support team)
□ 19. Тестовий end-to-end платіж у production Sandbox виконано

Юридична готовність
□ 20. Договір з PSP підписано, публічна оферта + конфіденційність розміщені

Корисні посилання

LiqPay

Офіційна документація LiqPay API (Acquiring)

Monobank

Офіційна документація Monobank Acquiring API

Stripe

Офіційна документація Stripe (найкраща у галузі)

PCI SSC

PCI Security Standards Council — SAQ, вимоги, ресурси

НБУ

Нормативна база НБУ з платіжних послуг

Підсумок модуля

Ви пройшли повний шлях: від розуміння того, що відбувається за лаштунками кожного платежу (чотирьохстороння модель, авторизація → клірінг → розрахунок), до практичної реалізації трьох провайдерів на абстракції IPaymentProvider, глибокого розуміння webhook, підписок та повернень.

Ключові принципи, що залишаться з вами назавжди:

  1. Не торкайся даних карток — делегуй PSP
  2. Ідемпотентність — захист від дублювань на всіх рівнях
  3. Стан-машина — чітка модель переходів між статусами платежу
  4. Verification через підпис — ніколи не довіряй webhook без перевірки
  5. Тестуй на кожному рівні — unit, integration, sandbox

Платіжний код вимагає максимальної уваги до деталей. Зате система, що правильно реалізована, стає конкурентною перевагою вашого продукту — надійністю, яку клієнти відчувають кожного разу, коли натискають «Оплатити».