generated from PenaSide/GolangTemplate
422 lines
15 KiB
Go
422 lines
15 KiB
Go
package wallet_client
|
|
|
|
import (
|
|
"context"
|
|
"github.com/gofiber/fiber/v2"
|
|
"go.uber.org/zap"
|
|
"fmt"
|
|
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
|
|
"gitea.pena/PenaSide/customer/internal/errors"
|
|
"gitea.pena/PenaSide/customer/internal/interface/client"
|
|
"gitea.pena/PenaSide/customer/internal/interface/controller/http"
|
|
"gitea.pena/PenaSide/customer/internal/interface/repository"
|
|
"gitea.pena/PenaSide/customer/internal/models"
|
|
"gitea.pena/PenaSide/customer/internal/proto/treasurer"
|
|
"gitea.pena/PenaSide/customer/internal/utils"
|
|
"gitea.pena/PenaSide/customer/pkg/validate"
|
|
)
|
|
|
|
type Deps struct {
|
|
MiddleWare *http.MiddleWare
|
|
AuthClient *client.AuthClient
|
|
PaymentClient *client.PaymentClient
|
|
GRPC *models.ConfigurationGRPC
|
|
AccountRepo *repository.AccountRepository
|
|
CurrencyClient *client.CurrencyClient
|
|
VerifyClient *client.VerificationClient
|
|
MailClient *client.MailClient
|
|
Logger *zap.Logger
|
|
TelegramClient *client.TelegramClient
|
|
}
|
|
|
|
type WalletController struct {
|
|
middleWare *http.MiddleWare
|
|
authClient *client.AuthClient
|
|
paymentClient *client.PaymentClient
|
|
grpc *models.ConfigurationGRPC
|
|
accountRepo *repository.AccountRepository
|
|
currencyClient *client.CurrencyClient
|
|
verifyClient *client.VerificationClient
|
|
mailClient *client.MailClient
|
|
logger *zap.Logger
|
|
telegramClient *client.TelegramClient
|
|
}
|
|
|
|
func NewWalletController(deps Deps) *WalletController {
|
|
return &WalletController{
|
|
middleWare: deps.MiddleWare,
|
|
authClient: deps.AuthClient,
|
|
paymentClient: deps.PaymentClient,
|
|
grpc: deps.GRPC,
|
|
accountRepo: deps.AccountRepo,
|
|
currencyClient: deps.CurrencyClient,
|
|
verifyClient: deps.VerifyClient,
|
|
mailClient: deps.MailClient,
|
|
logger: deps.Logger,
|
|
telegramClient: deps.TelegramClient,
|
|
}
|
|
}
|
|
|
|
func (receiver *WalletController) RequestMoney(ctx *fiber.Ctx) error {
|
|
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
|
if !ok || userID == "" {
|
|
return receiver.middleWare.NoAuth(ctx)
|
|
}
|
|
token, _ := receiver.middleWare.ExtractToken(ctx)
|
|
|
|
hlogger := log_mw.ExtractLogger(ctx)
|
|
|
|
var request models.GetPaymentLinkBody
|
|
if err := ctx.BodyParser(&request); err != nil {
|
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind payment link")
|
|
}
|
|
|
|
if err := utils.ValidateGetPaymentLinkBody(&request); err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
account, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
link, err := receiver.GetPaymentLink(ctx.Context(), &models.GetPaymentLinkRequest{
|
|
Body: &request,
|
|
UserID: userID,
|
|
ClientIP: ctx.IP(),
|
|
}, account, token)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
hlogger.Emit(models.InfoRequestMoney{
|
|
CtxUserID: userID,
|
|
CtxAccountID: account.ID,
|
|
KeyPaymentType: string(request.Type),
|
|
KeyCurrency: request.Currency,
|
|
CtxPrice: request.Amount,
|
|
CtxReturnURL: link,
|
|
})
|
|
|
|
return ctx.Status(fiber.StatusOK).JSON(&models.GetPaymentLinkResponse{Link: link})
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLink(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, token string) (string, errors.Error) {
|
|
auth, userErr := receiver.authClient.GetUser(ctx, request.UserID)
|
|
if userErr != nil {
|
|
receiver.logger.Error("failed to get user on <GetPaymentLink> on <PaymentService>",
|
|
zap.Error(userErr),
|
|
zap.String("userID", request.UserID),
|
|
)
|
|
|
|
return "", userErr
|
|
}
|
|
|
|
if auth.PhoneNumber == "+7" {
|
|
auth.PhoneNumber = ""
|
|
}
|
|
|
|
verification, err := receiver.verifyClient.GetVerification(ctx, token, request.UserID)
|
|
if err != nil {
|
|
verification = &models.Verification{
|
|
TaxNumber: "",
|
|
}
|
|
}
|
|
|
|
switch request.Body.Type {
|
|
case models.PaymentTypeBankCard:
|
|
return receiver.GetPaymentLinkBankCard(ctx, request, account, auth, verification)
|
|
case models.PaymentTypeYoomoney:
|
|
return receiver.GetPaymentLinkYooMoney(ctx, request, account, auth, verification)
|
|
case models.PaymentTypeSberPay:
|
|
return receiver.GetPaymentLinkSberPay(ctx, request, account, auth, verification)
|
|
case models.PaymentTypeTinkoff:
|
|
return receiver.GetPaymentLinkTinkoff(ctx, request, account, auth, verification)
|
|
case models.PaymentTypeSBP:
|
|
return receiver.GetPaymentLinkSBP(ctx, request, account, auth, verification)
|
|
case models.PaymentTypeSberB2B:
|
|
return receiver.GetPaymentLinkB2B(ctx, request, account, auth, verification)
|
|
}
|
|
|
|
return "", errors.NewWithMessage("invalid payment method type", errors.ErrInvalidArgs)
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLinkBankCard(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, auth *models.User, ver *models.Verification) (string, errors.Error) {
|
|
link, err := receiver.paymentClient.GetPaymentLinkBankCard(ctx, &treasurer.GetPaymentLinkRequest{
|
|
MainSettings: &treasurer.MainPaymentSettings{
|
|
Currency: request.Body.Currency,
|
|
Amount: request.Body.Amount,
|
|
UserID: request.UserID,
|
|
ClientIP: request.ClientIP,
|
|
CallbackHostGRPC: []string{receiver.grpc.Domen},
|
|
ReturnURL: request.Body.ReturnURL,
|
|
Customer: &treasurer.Customer{
|
|
FullName: account.Name.Orgname + ". " + account.Name.FirstName + " " + account.Name.Secondname,
|
|
Email: auth.Login,
|
|
Phone: auth.PhoneNumber,
|
|
},
|
|
Items: []*treasurer.Item{&treasurer.Item{
|
|
Description: "Пополнение пользовательского баланса платформы Pena Hub",
|
|
Quantity: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
Currency: "RUB",
|
|
Money: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
}},
|
|
},
|
|
})
|
|
if err != nil {
|
|
receiver.logger.Error("failed to get bankcard payment link on <GetPaymentLinkBankCard> of <PaymentService>", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return link, nil
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLinkYooMoney(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, auth *models.User, ver *models.Verification) (string, errors.Error) {
|
|
link, err := receiver.paymentClient.GetPaymentLinkYooMoney(ctx, &treasurer.GetPaymentLinkRequest{
|
|
MainSettings: &treasurer.MainPaymentSettings{
|
|
Currency: request.Body.Currency,
|
|
Amount: request.Body.Amount,
|
|
UserID: request.UserID,
|
|
ClientIP: request.ClientIP,
|
|
CallbackHostGRPC: []string{receiver.grpc.Domen},
|
|
ReturnURL: request.Body.ReturnURL,
|
|
Customer: &treasurer.Customer{
|
|
FullName: account.Name.Orgname + ", " + account.Name.FirstName + " " + account.Name.Secondname,
|
|
Email: auth.Login,
|
|
Phone: auth.PhoneNumber,
|
|
},
|
|
Items: []*treasurer.Item{&treasurer.Item{
|
|
Description: "Пополнение пользовательского баланса платформы Pena Hub",
|
|
Quantity: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
Currency: "RUB",
|
|
Money: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
}},
|
|
},
|
|
})
|
|
if err != nil {
|
|
receiver.logger.Error("failed to get yoomoney payment link on <GetPaymentLinkYooMoney> of <PaymentService>", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return link, nil
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLinkSberPay(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, auth *models.User, ver *models.Verification) (string, errors.Error) {
|
|
link, err := receiver.paymentClient.GetPaymentLinkSberPay(ctx, &treasurer.GetPaymentLinkRequest{
|
|
MainSettings: &treasurer.MainPaymentSettings{
|
|
Currency: request.Body.Currency,
|
|
Amount: request.Body.Amount,
|
|
UserID: request.UserID,
|
|
ClientIP: request.ClientIP,
|
|
CallbackHostGRPC: []string{receiver.grpc.Domen},
|
|
ReturnURL: request.Body.ReturnURL,
|
|
Customer: &treasurer.Customer{
|
|
FullName: account.Name.Orgname + ", " + account.Name.FirstName + " " + account.Name.Secondname,
|
|
Email: auth.Login,
|
|
Phone: auth.PhoneNumber,
|
|
},
|
|
Items: []*treasurer.Item{&treasurer.Item{
|
|
Description: "Пополнение пользовательского баланса платформы Pena Hub",
|
|
Quantity: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
Currency: "RUB",
|
|
Money: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
}},
|
|
},
|
|
})
|
|
if err != nil {
|
|
receiver.logger.Error("failed to get sberpay payment link on <GetPaymentLinkSberPay> of <PaymentService>", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return link, nil
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLinkTinkoff(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, auth *models.User, ver *models.Verification) (string, errors.Error) {
|
|
link, err := receiver.paymentClient.GetPaymentLinkTinkoff(ctx, &treasurer.GetPaymentLinkRequest{
|
|
MainSettings: &treasurer.MainPaymentSettings{
|
|
Currency: request.Body.Currency,
|
|
Amount: request.Body.Amount,
|
|
UserID: request.UserID,
|
|
ClientIP: request.ClientIP,
|
|
CallbackHostGRPC: []string{receiver.grpc.Domen},
|
|
ReturnURL: request.Body.ReturnURL,
|
|
Customer: &treasurer.Customer{
|
|
FullName: account.Name.Orgname + ", " + account.Name.FirstName + " " + account.Name.Secondname,
|
|
Email: auth.Login,
|
|
Phone: auth.PhoneNumber,
|
|
},
|
|
Items: []*treasurer.Item{&treasurer.Item{
|
|
Description: "Пополнение пользовательского баланса платформы Pena Hub",
|
|
Quantity: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
Currency: "RUB",
|
|
Money: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
}},
|
|
},
|
|
})
|
|
if err != nil {
|
|
receiver.logger.Error("failed to get tinkoff payment link on <GetPaymentLinkTinkoff> of <PaymentService>", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return link, nil
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLinkSBP(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, auth *models.User, ver *models.Verification) (string, errors.Error) {
|
|
link, err := receiver.paymentClient.GetPaymentLinkSBP(ctx, &treasurer.GetPaymentLinkRequest{
|
|
MainSettings: &treasurer.MainPaymentSettings{
|
|
Currency: request.Body.Currency,
|
|
Amount: request.Body.Amount,
|
|
UserID: request.UserID,
|
|
ClientIP: request.ClientIP,
|
|
CallbackHostGRPC: []string{receiver.grpc.Domen},
|
|
ReturnURL: request.Body.ReturnURL,
|
|
Customer: &treasurer.Customer{
|
|
FullName: account.Name.Orgname + ", " + account.Name.FirstName + " " + account.Name.Secondname,
|
|
Email: auth.Login,
|
|
Phone: auth.PhoneNumber,
|
|
},
|
|
Items: []*treasurer.Item{&treasurer.Item{
|
|
Description: "Пополнение пользовательского баланса платформы Pena Hub",
|
|
Quantity: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
Currency: "RUB",
|
|
Money: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
}},
|
|
},
|
|
})
|
|
if err != nil {
|
|
receiver.logger.Error("failed to get sbp payment link on <GetPaymentLinkSBP> of <PaymentService>", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return link, nil
|
|
}
|
|
|
|
func (receiver *WalletController) GetPaymentLinkB2B(ctx context.Context, request *models.GetPaymentLinkRequest, account *models.Account, auth *models.User, ver *models.Verification) (string, errors.Error) {
|
|
link, err := receiver.paymentClient.GetPaymentLinkSberbankB2B(ctx, &treasurer.GetPaymentLinkRequest{
|
|
MainSettings: &treasurer.MainPaymentSettings{
|
|
Currency: request.Body.Currency,
|
|
Amount: request.Body.Amount,
|
|
UserID: request.UserID,
|
|
ClientIP: request.ClientIP,
|
|
CallbackHostGRPC: []string{receiver.grpc.Domen},
|
|
ReturnURL: request.Body.ReturnURL,
|
|
Customer: &treasurer.Customer{
|
|
FullName: account.Name.Orgname + ", " + account.Name.FirstName + " " + account.Name.Secondname,
|
|
Email: auth.Login,
|
|
Phone: auth.PhoneNumber,
|
|
},
|
|
Items: []*treasurer.Item{&treasurer.Item{
|
|
Description: "Пополнение пользовательского баланса платформы Pena Hub",
|
|
Quantity: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
Currency: "RUB",
|
|
Money: fmt.Sprintf("%.2f", float64(request.Body.Amount)/100),
|
|
}},
|
|
},
|
|
})
|
|
if err != nil {
|
|
receiver.logger.Error("failed to get sberbankb2b payment link on <GetPaymentLinkB2B> of <PaymentService>", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
return link, nil
|
|
}
|
|
|
|
func (receiver *WalletController) ChangeCurrency(ctx *fiber.Ctx) error {
|
|
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
|
if !ok || userID == "" {
|
|
return receiver.middleWare.NoAuth(ctx)
|
|
}
|
|
|
|
var request models.ChangeCurrency
|
|
if err := ctx.BodyParser(&request); err != nil {
|
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind currency")
|
|
}
|
|
|
|
if validate.IsStringEmpty(request.Currency) {
|
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "empty currency")
|
|
}
|
|
|
|
currency := request.Currency
|
|
account, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
cash, err := receiver.currencyClient.Translate(ctx.Context(), &models.TranslateCurrency{
|
|
Money: account.Wallet.Cash,
|
|
From: account.Wallet.Currency,
|
|
To: currency,
|
|
})
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
updatedAccount, err := receiver.accountRepo.ChangeWallet(ctx.Context(), account.UserID, &models.Wallet{
|
|
Cash: cash,
|
|
Currency: currency,
|
|
Money: account.Wallet.Money,
|
|
})
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusOK).JSON(updatedAccount)
|
|
}
|
|
|
|
func (receiver *WalletController) PostWalletRspay(ctx *fiber.Ctx) error {
|
|
userID, ok := receiver.middleWare.ExtractUserID(ctx)
|
|
if !ok || userID == "" {
|
|
return receiver.middleWare.NoAuth(ctx)
|
|
}
|
|
|
|
hlogger := log_mw.ExtractLogger(ctx)
|
|
|
|
var req struct {
|
|
Money *float32 `json:"money,omitempty"`
|
|
}
|
|
|
|
if err := ctx.BodyParser(&req); err != nil {
|
|
receiver.logger.Error("failed to bind request", zap.Error(err))
|
|
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind request")
|
|
}
|
|
|
|
user, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
if user.Status != models.AccountStatusNko && user.Status != models.AccountStatusOrg {
|
|
return receiver.middleWare.Error(ctx, fiber.StatusForbidden, "not allowed for non organizations")
|
|
}
|
|
token := ctx.Get("Authorization")
|
|
|
|
verification, err := receiver.verifyClient.GetVerification(ctx.Context(), token, userID)
|
|
if err == errors.ErrNotFound {
|
|
return receiver.middleWare.Error(ctx, fiber.StatusForbidden, "no verification data found")
|
|
}
|
|
|
|
authData, err := receiver.authClient.GetUser(ctx.Context(), userID)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
err = receiver.mailClient.SendMessage(authData.Login, verification, *req.Money)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
err = receiver.telegramClient.NotifyRsPay(authData.Login, verification, *req.Money)
|
|
if err != nil {
|
|
return receiver.middleWare.ErrorOld(ctx, err)
|
|
}
|
|
|
|
hlogger.Emit(models.InfoRSPay{
|
|
CtxUserID: userID,
|
|
CtxAccountID: user.ID,
|
|
CtxPrice: int64(*req.Money),
|
|
CtxLogin: authData.Login,
|
|
})
|
|
|
|
return ctx.SendStatus(fiber.StatusOK)
|
|
}
|