treasurer/internal/controller/http_controllers/payment/payment.go

85 lines
2.9 KiB
Go

package payment
import (
"fmt"
"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 <NewPaymentController>", errors.ErrInvalidArgs)
}
if len(deps.PaymentProviders) == 0 {
return nil, errors.NewWithMessage("No payment providers provided on <NewPaymentController>", 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 payment_provider.PaymentRequest
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.PaymentMethod)
if err != nil {
receiver.logger.Error("failed to get payment provider", zap.String("paymentMethod", string(req.PaymentMethod)), zap.Error(err))
return errors.HTTP(ctx, err)
}
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)
}