86 lines
3.0 KiB
Go
86 lines
3.0 KiB
Go
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 <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 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)
|
||
}
|