package payment import ( "fmt" "gitea.pena/PenaSide/treasurer/internal/models/yandex" "gitea.pena/PenaSide/treasurer/internal/payment_provider" "github.com/gofiber/fiber/v2" "sync" "gitea.pena/PenaSide/treasurer/internal/errors" "gitea.pena/PenaSide/treasurer/internal/models" "go.uber.org/zap" ) type PaymentControllerDeps struct { Logger *zap.Logger PaymentProviders []payment_provider.PaymentProvider } type PaymentController struct { logger *zap.Logger paymentProviders []payment_provider.PaymentProvider providerMap map[models.PaymentType][]payment_provider.PaymentProvider mu sync.RWMutex } func NewPaymentController(deps PaymentControllerDeps) (*PaymentController, errors.Error) { if deps.Logger == nil { return nil, errors.NewWithMessage("Logger is nil on ", errors.ErrInvalidArgs) } if len(deps.PaymentProviders) == 0 { return nil, errors.NewWithMessage("No payment providers provided on ", errors.ErrInvalidArgs) } controller := &PaymentController{ logger: deps.Logger, paymentProviders: deps.PaymentProviders, providerMap: make(map[models.PaymentType][]payment_provider.PaymentProvider), } for _, provider := range deps.PaymentProviders { for _, method := range provider.GetSupportedPaymentMethods() { controller.providerMap[method] = append(controller.providerMap[method], provider) } } return controller, nil } // TODO Добавить более сложную логику выбора провайдера (приоритеты, доступность и т.д.) func (receiver *PaymentController) getProviderForPaymentMethod(method models.PaymentType) (payment_provider.PaymentProvider, errors.Error) { receiver.mu.RLock() defer receiver.mu.RUnlock() providers, exists := receiver.providerMap[method] if !exists || len(providers) == 0 { return nil, errors.NewWithMessage("no provider found for payment method", errors.ErrNotFound) } return providers[0], nil } // обрабатывает запрос на создание платежа func (receiver *PaymentController) CreatePayment(ctx *fiber.Ctx) error { var req models.CreatePayment[yandex.Receipt] if err := ctx.BodyParser(&req); err != nil { receiver.logger.Error("failed to parse payment request", zap.Error(err)) return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError)) } provider, err := receiver.getProviderForPaymentMethod(req.Type) if err != nil { receiver.logger.Error("failed to get payment provider", zap.String("paymentMethod", string(req.Type)), zap.Error(err)) return errors.HTTP(ctx, err) } // todo потом нужно будет сделать так чтобы работало не только с yandex.Receipt resp, err := provider.CreateInvoice(ctx.Context(), &req) if err != nil { receiver.logger.Error("failed to create payment", zap.String("provider", provider.GetName()), zap.Error(err)) return errors.HTTP(ctx, err) } return ctx.JSON(resp) }