From 330d8753e036a72b303cdf7e4de0ee31b651ed5e Mon Sep 17 00:00:00 2001 From: Pasha Date: Tue, 22 Jul 2025 14:16:36 +0300 Subject: [PATCH] added logic for create invoice --- internal/models/payment.go | 5 +- internal/payment_provider/alchemy/provider.go | 49 +++++++++++++++++-- internal/repository/payment.go | 31 +++++++----- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/internal/models/payment.go b/internal/models/payment.go index 46cdfda..c14f90b 100644 --- a/internal/models/payment.go +++ b/internal/models/payment.go @@ -30,8 +30,9 @@ type Payment struct { */ CallbackHostGRPC []string `json:"callbackHostGrpc" bson:"callbackHostGrpc"` - WalletAddress string `json:"walletAddress" bson:"walletAddress"` // for crypto - CryptoAmount float64 `json:"cryptoAmount" bson:"cryptoAmount"` // for crypto + ToWalletAddress string `json:"toWalletAddress" bson:"toWalletAddress"` // for crypto our + FromWalletAddress string `json:"fromWalletAddress" bson:"fromWalletAddress"` // for crypto them + CryptoAmount float64 `json:"cryptoAmount" bson:"cryptoAmount"` // for crypto } func (p *Payment) Sanitize() *Payment { diff --git a/internal/payment_provider/alchemy/provider.go b/internal/payment_provider/alchemy/provider.go index b55bce5..802933c 100644 --- a/internal/payment_provider/alchemy/provider.go +++ b/internal/payment_provider/alchemy/provider.go @@ -9,6 +9,9 @@ import ( "gitea.pena/PenaSide/treasurer/internal/repository" "github.com/gofiber/fiber/v2" "go.uber.org/zap" + "strconv" + "strings" + "time" ) const ProviderName = "alchemy" @@ -44,9 +47,49 @@ func (p *Provider) GetSupportedPaymentMethods() []models.PaymentType { return []models.PaymentType{models.PaymentTypeAlchemy} } -// todo func (p *Provider) CreateInvoice(ctx context.Context, req map[string]string) (string, errors.Error) { - return "", nil + amountStr := req["cryptoAmount"] + fromWallet := req["fromWalletAddress"] + if amountStr == "" || fromWallet == "" { + p.logger.Error("amount or fromWallet address is empty", zap.String("fromWalletAddress", fromWallet), zap.String("cryptoAmount", amountStr)) + return "", errors.NewWithMessage("cryptoAmount and fromWalletAddress required", errors.ErrInvalidArgs) + } + + cryptoAmount, err := strconv.ParseFloat(amountStr, 64) + if err != nil { + p.logger.Error("failed to parse cryptoAmount from wallet address", zap.Error(err)) + return "", errors.NewWithMessage("invalid cryptoAmount", errors.ErrInvalidArgs) + } + + now := time.Now() + payment := &models.Payment{ + UserID: req["user_id"], + ClientIP: req["client_ip"], + Currency: req["currency"], + Type: models.PaymentType(req["type"]), + Status: models.PaymentStatusWaiting, + Completed: false, + IsDeleted: false, + CreatedAt: now, + UpdatedAt: now, + ToWalletAddress: p.config.WalletAddress, + FromWalletAddress: fromWallet, + CryptoAmount: cryptoAmount, + } + + var callbackHosts []string + if val, ok := req["callback_host_grpc"]; ok && val != "" { + callbackHosts = strings.Split(val, ",") + } + payment.CallbackHostGRPC = callbackHosts + + _, err = p.repository.Insert(ctx, payment) + if err != nil { + p.logger.Error("failed to insert payment into database", zap.Error(err)) + return "", errors.NewWithMessage(fmt.Sprintf("failed to insert payment into database: %v", err), errors.ErrInternalError) + } + + return p.config.WalletAddress, nil } func (p *Provider) RegisterWebhookHandlers(router fiber.Router) { @@ -63,7 +106,7 @@ func (p *Provider) handleWebhook(ctx *fiber.Ctx) error { if act.ToAddress != p.config.WalletAddress { continue } - payment, err := p.repository.FindByWalletAddressAndAmount(ctx.Context(), act.FromAddress, act.Value) + payment, err := p.repository.FindByWalletsAndAmount(ctx.Context(), act.ToAddress, act.FromAddress, act.Value) if err != nil { if err.Type() == errors.ErrNotFound { return ctx.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("payment not found: %s", err.Error())) diff --git a/internal/repository/payment.go b/internal/repository/payment.go index 17b957b..eee0907 100644 --- a/internal/repository/payment.go +++ b/internal/repository/payment.go @@ -32,8 +32,10 @@ var PaymentFields = struct { RawPaymentBody string CallbackHostGRPC string - WalletAddress string // for crypto - CryptoAmount string // for crypto + WalletAddress string // for crypto + CryptoAmount string // for crypto + ToWalletAddress string + FromWalletAddress string }{ ID: "_id", UserID: "userId", @@ -52,8 +54,10 @@ var PaymentFields = struct { RawPaymentBody: "rawPaymentBody", CallbackHostGRPC: "callbackHostGrpc", - WalletAddress: "walletAddress", - CryptoAmount: "cryptoAmount", + WalletAddress: "walletAddress", + CryptoAmount: "cryptoAmount", + ToWalletAddress: "toWalletAddress", + FromWalletAddress: "fromWalletAddress", } type PaymentRepositoryDeps struct { @@ -163,22 +167,25 @@ func (r *PaymentRepository) SetPaymentStatus(ctx context.Context, paymentID stri return &payment, nil } -func (r *PaymentRepository) FindByWalletAddressAndAmount(ctx context.Context, walletAddress string, cryptoAmount float64) (*models.Payment, errors.Error) { +func (r *PaymentRepository) FindByWalletsAndAmount(ctx context.Context, toWalletAddress, fromWalletAddress string, cryptoAmount float64) (*models.Payment, errors.Error) { payment := models.Payment{} filter := bson.M{ - PaymentFields.WalletAddress: walletAddress, - PaymentFields.CryptoAmount: cryptoAmount, - PaymentFields.Completed: false, //не завершённые + PaymentFields.ToWalletAddress: toWalletAddress, + PaymentFields.FromWalletAddress: fromWalletAddress, + PaymentFields.CryptoAmount: cryptoAmount, + PaymentFields.Completed: false, + PaymentFields.Status: models.PaymentStatusWaiting, } if err := r.collection.FindOne(ctx, filter).Decode(&payment); err != nil { - r.logger.Error("failed to find payment by walletAddress and amount on of ", + r.logger.Error("failed to find payment by wallets and amount on of ", zap.Error(err), - zap.String("walletAddress", walletAddress), - zap.Float64("amount", cryptoAmount), + zap.String("toWalletAddress", toWalletAddress), + zap.String("fromWalletAddress", fromWalletAddress), + zap.Float64("cryptoAmount", cryptoAmount), ) findErr := errors.NewWithError( - fmt.Errorf("failed to find payment by walletAddress and amount: %w", err), + fmt.Errorf("failed to find payment by wallets and amount: %w", err), errors.ErrInternalError, )