> Как задаются стратегии для каждого платежа: через API или иначе (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: InDrive
Стек: Go
> Пример ответа
Короткий ответ
Стратегии для каждого платежа задаются через API - это стандартный подход в платёжных системах. Клиент передаёт идентификатор стратегии или её параметры в запросе на создание платежа. Сервер валидирует стратегию, применяет её к конкретному платежу и сохраняет связь в БД. Альтернатива - конфигурация на стороне сервера, но она менее гибкая и не позволяет клиенту управлять поведением в рантайме.
Подробное объяснение
В платёжных системах стратегия определяет набор правил и параметров обработки платежа: выбор провайдера, порядок ретраев, лимиты, таймауты, логику фолбэка. Есть два основных способа задания стратегии:
-
Через API - клиент передаёт стратегию в теле запроса при создании платежа. Это может быть:
- идентификатор заранее определённой стратегии (например,
strategy_id = "default_retry_3"); - инлайн-параметры (например,
retry_count = 3,provider_priority = ["stripe", "adyen"]); - комбинация: базовый шаблон + переопределение отдельных полей.
- идентификатор заранее определённой стратегии (например,
-
Через конфигурацию на сервере - стратегия назначается автоматически на основе атрибутов платежа (сумма, валюта, страна, merchant_id). Клиент не управляет этим напрямую.
На практике используют гибридный подход: сервер имеет набор дефолтных стратегий, а API позволяет клиенту выбрать одну из них или переопределить отдельные параметры. Это даёт гибкость и сохраняет контроль на стороне платёжной системы.
Ключевой момент - стратегия должна быть детерминированной для конкретного платежа: после создания платежа стратегия фиксируется и не может быть изменена без явного действия (например, через отдельный endpoint для обновления). Это важно для аудита и повторных попыток обработки.
На практике
В Go-сервисах стратегии обычно представлены как структуры с полями и методами. При получении запроса на создание платежа:
- Парсим входные данные, извлекаем
strategy_idили параметры стратегии. - Валидируем: проверяем существование стратегии, допустимость параметров, права доступа мерчанта.
- Создаём объект платежа, сохраняем стратегию в БД (обычно в отдельной таблице или JSON-колонке).
- Передаём платеж в обработчик, который использует стратегию для выбора провайдера и управления ретраями.
Важно: стратегия не должна быть частью бизнес-логики платежа - она должна быть данными, которые передаются в обработчик. Это позволяет менять поведение без изменения кода.
Пример кода
GOtype 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-кандидат упомянет вопросы версионирования стратегий и миграции при изменении параметров.
Типичные ошибки
- Ответ "стратегия задаётся в коде" - это неверно для платёжных систем, где стратегия должна быть изменяемой без деплоя.
- Игнорирование валидации: клиент не должен иметь возможность передать произвольную стратегию, которая нарушит бизнес-правила.
- Неупоминание фиксации стратегии на момент создания платежа - это частая ошибка, которая приводит к несогласованности при ретраях.
- Смешивание стратегии с бизнес-логикой платежа: стратегия - это данные, а не код.
> Похожие задачи по Go
Как исправлять застрявшие платежи вручную при наличии реконсайл-джобы
Как следить за работой оркестратора и какие метрики использовать для проверки корректности
Какой тип ID является последовательным?
Как происходит эвакуация элементов в хэш-таблице?
> Похожие задачи по backend
Как исправлять застрявшие платежи вручную при наличии реконсайл-джобы
Как следить за работой оркестратора и какие метрики использовать для проверки корректности
Как реализовать коллекцию для хранения связи между customerId, accountNumber и статусом ареста счета без использования объектов?
Какой тип ID является последовательным?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью