> Как задаются стратегии для каждого платежа: через API или иначе (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: InDrive

Стек: Go

> Пример ответа

Короткий ответ

Стратегии для каждого платежа задаются через API - это стандартный подход в платёжных системах. Клиент передаёт идентификатор стратегии или её параметры в запросе на создание платежа. Сервер валидирует стратегию, применяет её к конкретному платежу и сохраняет связь в БД. Альтернатива - конфигурация на стороне сервера, но она менее гибкая и не позволяет клиенту управлять поведением в рантайме.

Подробное объяснение

В платёжных системах стратегия определяет набор правил и параметров обработки платежа: выбор провайдера, порядок ретраев, лимиты, таймауты, логику фолбэка. Есть два основных способа задания стратегии:

  1. Через API - клиент передаёт стратегию в теле запроса при создании платежа. Это может быть:

    • идентификатор заранее определённой стратегии (например, strategy_id = "default_retry_3");
    • инлайн-параметры (например, retry_count = 3, provider_priority = ["stripe", "adyen"]);
    • комбинация: базовый шаблон + переопределение отдельных полей.
  2. Через конфигурацию на сервере - стратегия назначается автоматически на основе атрибутов платежа (сумма, валюта, страна, merchant_id). Клиент не управляет этим напрямую.

На практике используют гибридный подход: сервер имеет набор дефолтных стратегий, а API позволяет клиенту выбрать одну из них или переопределить отдельные параметры. Это даёт гибкость и сохраняет контроль на стороне платёжной системы.

Ключевой момент - стратегия должна быть детерминированной для конкретного платежа: после создания платежа стратегия фиксируется и не может быть изменена без явного действия (например, через отдельный endpoint для обновления). Это важно для аудита и повторных попыток обработки.

На практике

В Go-сервисах стратегии обычно представлены как структуры с полями и методами. При получении запроса на создание платежа:

  1. Парсим входные данные, извлекаем strategy_id или параметры стратегии.
  2. Валидируем: проверяем существование стратегии, допустимость параметров, права доступа мерчанта.
  3. Создаём объект платежа, сохраняем стратегию в БД (обычно в отдельной таблице или JSON-колонке).
  4. Передаём платеж в обработчик, который использует стратегию для выбора провайдера и управления ретраями.

Важно: стратегия не должна быть частью бизнес-логики платежа - она должна быть данными, которые передаются в обработчик. Это позволяет менять поведение без изменения кода.

Пример кода

GO
type PaymentStrategy struct {
ID string `json:"id"`
ProviderOrder []string `json:"provider_order"`
RetryCount int `json:"retry_count"`
RetryDelay time.Duration `json:"retry_delay"`
FallbackEnabled bool `json:"fallback_enabled"`
}
type CreatePaymentRequest struct {
Amount int64 `json:"amount"`
Currency string `json:"currency"`
StrategyID string `json:"strategy_id,omitempty"`
Strategy *PaymentStrategy `json:"strategy,omitempty"`
}
func (s *Service) CreatePayment(ctx context.Context, req *CreatePaymentRequest) (*Payment, error) {
strategy, err := s.resolveStrategy(ctx, req)
if err != nil {
return nil, err
}
payment := &Payment{
Amount: req.Amount,
Currency: req.Currency,
Strategy: strategy,
Status: StatusPending,
}
if err := s.store.SavePayment(ctx, payment); err != nil {
return nil, err
}
return payment, nil
}
func (s *Service) resolveStrategy(ctx context.Context, req *CreatePaymentRequest) (*PaymentStrategy, error) {
if req.StrategyID != "" {
return s.strategyRepo.GetByID(ctx, req.StrategyID)
}
if req.Strategy != nil {
return req.Strategy, nil
}
return s.strategyRepo.GetDefault(ctx)
}

Как отвечать на собеседовании

Начните с прямого ответа: стратегии задаются через API, но с поддержкой серверных дефолтов. Затем объясните, почему это правильный подход: гибкость для клиентов, централизованный контроль, возможность A/B-тестирования. Упомяните, что стратегия фиксируется на момент создания платежа - это важно для консистентности. Если спросят про безопасность, скажите, что стратегия валидируется на сервере, и клиент не может передать произвольные параметры, которые нарушат лимиты или приведут к некорректной маршрутизации.

Что проверяет интервьюер

Интервьюер проверяет понимание архитектуры платёжных систем, умение проектировать API, знание trade-off между гибкостью и контролем. Также важно, что вы понимаете разницу между конфигурацией и кодом, и как стратегия влияет на жизненный цикл платежа. Ожидается, что senior-кандидат упомянет вопросы версионирования стратегий и миграции при изменении параметров.

Типичные ошибки

  • Ответ "стратегия задаётся в коде" - это неверно для платёжных систем, где стратегия должна быть изменяемой без деплоя.
  • Игнорирование валидации: клиент не должен иметь возможность передать произвольную стратегию, которая нарушит бизнес-правила.
  • Неупоминание фиксации стратегии на момент создания платежа - это частая ошибка, которая приводит к несогласованности при ретраях.
  • Смешивание стратегии с бизнес-логикой платежа: стратегия - это данные, а не код.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью