added logic for create invoice

This commit is contained in:
Pasha 2025-07-22 14:16:36 +03:00
parent 570b1c0d2e
commit 330d8753e0
3 changed files with 68 additions and 17 deletions

@ -30,8 +30,9 @@ type Payment struct {
*/ */
CallbackHostGRPC []string `json:"callbackHostGrpc" bson:"callbackHostGrpc"` CallbackHostGRPC []string `json:"callbackHostGrpc" bson:"callbackHostGrpc"`
WalletAddress string `json:"walletAddress" bson:"walletAddress"` // for crypto ToWalletAddress string `json:"toWalletAddress" bson:"toWalletAddress"` // for crypto our
CryptoAmount float64 `json:"cryptoAmount" bson:"cryptoAmount"` // for crypto FromWalletAddress string `json:"fromWalletAddress" bson:"fromWalletAddress"` // for crypto them
CryptoAmount float64 `json:"cryptoAmount" bson:"cryptoAmount"` // for crypto
} }
func (p *Payment) Sanitize() *Payment { func (p *Payment) Sanitize() *Payment {

@ -9,6 +9,9 @@ import (
"gitea.pena/PenaSide/treasurer/internal/repository" "gitea.pena/PenaSide/treasurer/internal/repository"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"go.uber.org/zap" "go.uber.org/zap"
"strconv"
"strings"
"time"
) )
const ProviderName = "alchemy" const ProviderName = "alchemy"
@ -44,9 +47,49 @@ func (p *Provider) GetSupportedPaymentMethods() []models.PaymentType {
return []models.PaymentType{models.PaymentTypeAlchemy} return []models.PaymentType{models.PaymentTypeAlchemy}
} }
// todo
func (p *Provider) CreateInvoice(ctx context.Context, req map[string]string) (string, errors.Error) { 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) { 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 { if act.ToAddress != p.config.WalletAddress {
continue 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 != nil {
if err.Type() == errors.ErrNotFound { if err.Type() == errors.ErrNotFound {
return ctx.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("payment not found: %s", err.Error())) return ctx.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("payment not found: %s", err.Error()))

@ -32,8 +32,10 @@ var PaymentFields = struct {
RawPaymentBody string RawPaymentBody string
CallbackHostGRPC string CallbackHostGRPC string
WalletAddress string // for crypto WalletAddress string // for crypto
CryptoAmount string // for crypto CryptoAmount string // for crypto
ToWalletAddress string
FromWalletAddress string
}{ }{
ID: "_id", ID: "_id",
UserID: "userId", UserID: "userId",
@ -52,8 +54,10 @@ var PaymentFields = struct {
RawPaymentBody: "rawPaymentBody", RawPaymentBody: "rawPaymentBody",
CallbackHostGRPC: "callbackHostGrpc", CallbackHostGRPC: "callbackHostGrpc",
WalletAddress: "walletAddress", WalletAddress: "walletAddress",
CryptoAmount: "cryptoAmount", CryptoAmount: "cryptoAmount",
ToWalletAddress: "toWalletAddress",
FromWalletAddress: "fromWalletAddress",
} }
type PaymentRepositoryDeps struct { type PaymentRepositoryDeps struct {
@ -163,22 +167,25 @@ func (r *PaymentRepository) SetPaymentStatus(ctx context.Context, paymentID stri
return &payment, nil 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{} payment := models.Payment{}
filter := bson.M{ filter := bson.M{
PaymentFields.WalletAddress: walletAddress, PaymentFields.ToWalletAddress: toWalletAddress,
PaymentFields.CryptoAmount: cryptoAmount, PaymentFields.FromWalletAddress: fromWalletAddress,
PaymentFields.Completed: false, //не завершённые PaymentFields.CryptoAmount: cryptoAmount,
PaymentFields.Completed: false,
PaymentFields.Status: models.PaymentStatusWaiting,
} }
if err := r.collection.FindOne(ctx, filter).Decode(&payment); err != nil { if err := r.collection.FindOne(ctx, filter).Decode(&payment); err != nil {
r.logger.Error("failed to find payment by walletAddress and amount on <FindByWalletAddressAndAmount> of <PaymentRepository>", r.logger.Error("failed to find payment by wallets and amount on <FindByWalletsAndAmount> of <PaymentRepository>",
zap.Error(err), zap.Error(err),
zap.String("walletAddress", walletAddress), zap.String("toWalletAddress", toWalletAddress),
zap.Float64("amount", cryptoAmount), zap.String("fromWalletAddress", fromWalletAddress),
zap.Float64("cryptoAmount", cryptoAmount),
) )
findErr := errors.NewWithError( 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, errors.ErrInternalError,
) )