treasurer/internal/controller/grpc/payment.go
2025-06-12 14:45:22 +03:00

127 lines
4.8 KiB
Go

package grpc
import (
"context"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/payment_provider"
"gitea.pena/PenaSide/treasurer/internal/utils"
"strings"
"sync"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"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 in 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
}
func (r *PaymentController) getProviderForPaymentMethod(method models.PaymentType) (payment_provider.PaymentProvider, errors.Error) {
r.mu.RLock()
defer r.mu.RUnlock()
providers, exists := r.providerMap[method]
if !exists || len(providers) == 0 {
return nil, errors.NewWithMessage("no provider found for payment method", errors.ErrNotFound)
}
return providers[0], nil
}
func (r *PaymentController) createPayment(ctx context.Context, paymentType models.PaymentType, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
provider, err := r.getProviderForPaymentMethod(paymentType)
if err != nil {
r.logger.Error("failed to get payment provider",
zap.String("paymentMethod", string(paymentType)),
zap.Error(err))
return nil, errors.GRPC("failed to get payment provider", err)
}
request := map[string]string{
"type": string(paymentType),
"currency": in.MainSettings.Currency,
"amount": fmt.Sprintf("%d", in.MainSettings.Amount),
"callback_host_grpc": strings.Join(in.MainSettings.CallbackHostGRPC, ","),
"return_url": in.MainSettings.ReturnURL,
"user_id": in.MainSettings.UserID,
"client_ip": in.MainSettings.ClientIP,
"requisites": utils.ToJSON(yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
INN: in.MainSettings.Customer.INN,
Email: in.MainSettings.Customer.Email,
Phone: in.MainSettings.Customer.Phone,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
}),
}
link, err := provider.CreateInvoice(ctx, request)
if err != nil {
r.logger.Error("failed to create payment",
zap.String("provider", provider.GetName()),
zap.Error(err))
return nil, errors.GRPC("failed to create payment", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (r *PaymentController) GetPaymentLinkBankCard(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
r.logger.Info("f<GetPaymentLinkBankCard> of <PaymentController>", zap.Any("Customer", in.MainSettings.Customer))
return r.createPayment(ctx, models.PaymentTypeBankCard, in)
}
func (r *PaymentController) GetPaymentLinkYooMoney(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeYoomoney, in)
}
func (r *PaymentController) GetPaymentLinkTinkoff(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeTinkoff, in)
}
func (r *PaymentController) GetPaymentLinkSBP(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeSBP, in)
}
func (r *PaymentController) GetPaymentLinkSberPay(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeSberPay, in)
}
func (r *PaymentController) GetPaymentLinkSberbankB2B(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeSberB2B, in)
}