diff --git a/internal/models/payment.go b/internal/models/payment.go index d86d5f8..29766b0 100644 --- a/internal/models/payment.go +++ b/internal/models/payment.go @@ -29,6 +29,8 @@ type Payment struct { Запрос будет отправляться по протоколу GRPC */ CallbackHostGRPC []string `json:"callbackHostGrpc" bson:"callbackHostGrpc"` + + WalletAddress string // for crypto } func (p *Payment) Sanitize() *Payment { diff --git a/internal/payment_provider/alchemy/provider.go b/internal/payment_provider/alchemy/provider.go index a0791a4..2b6ba5a 100644 --- a/internal/payment_provider/alchemy/provider.go +++ b/internal/payment_provider/alchemy/provider.go @@ -6,6 +6,7 @@ import ( "gitea.pena/PenaSide/treasurer/internal/errors" "gitea.pena/PenaSide/treasurer/internal/models" "gitea.pena/PenaSide/treasurer/internal/models/alchemy" + "gitea.pena/PenaSide/treasurer/internal/repository" "github.com/gofiber/fiber/v2" "go.uber.org/zap" ) @@ -17,13 +18,15 @@ type Config struct { } type Provider struct { - logger *zap.Logger - config *Config + repository *repository.PaymentRepository + logger *zap.Logger + config *Config } type Deps struct { - Logger *zap.Logger - Config *Config + Repository *repository.PaymentMethodRepository + Logger *zap.Logger + Config *Config } func New(deps Deps) *Provider { @@ -59,7 +62,18 @@ func (p *Provider) handleWebhook(ctx *fiber.Ctx) error { if act.ToAddress != p.config.WalletAddress { continue } - //TODO: найти инвойс по act.Value и act.FromAddress + amountStr := fmt.Sprintf("%v", act.Value) + payment, err := p.repository.FindByWalletAddressAndAmount(ctx.Context(), act.FromAddress, amountStr) + if err != nil { + if err.Type() == errors.ErrNotFound { + return ctx.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("payment not found: %s", err.Error())) + } + return ctx.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("internal error while searching payment: %s", err.Error())) + } + _, err = p.repository.SetPaymentComplete(ctx.Context(), payment.PaymentID) + if err != nil { + return ctx.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("failed to set payment complete: %s", err.Error())) + } } return ctx.SendStatus(fiber.StatusOK) } diff --git a/internal/repository/payment.go b/internal/repository/payment.go index e4c8bee..316b3ee 100644 --- a/internal/repository/payment.go +++ b/internal/repository/payment.go @@ -31,6 +31,8 @@ var PaymentFields = struct { DeletedAt string RawPaymentBody string CallbackHostGRPC string + + WalletAddress string // for crypto }{ ID: "_id", UserID: "userId", @@ -48,6 +50,8 @@ var PaymentFields = struct { DeletedAt: "deletedAt", RawPaymentBody: "rawPaymentBody", CallbackHostGRPC: "callbackHostGrpc", + + WalletAddress: "walletAddress", } type PaymentRepositoryDeps struct { @@ -156,3 +160,32 @@ func (r *PaymentRepository) SetPaymentStatus(ctx context.Context, paymentID stri return &payment, nil } + +func (r *PaymentRepository) FindByWalletAddressAndAmount(ctx context.Context, walletAddress string, amount string) (*models.Payment, errors.Error) { + payment := models.Payment{} + filter := bson.M{ + PaymentFields.WalletAddress: walletAddress, + PaymentFields.Amount: amount, + PaymentFields.Completed: false, //не завершённые + } + if err := r.collection.FindOne(ctx, filter).Decode(&payment); err != nil { + r.logger.Error("failed to find payment by walletAddress and amount on of ", + zap.Error(err), + zap.String("walletAddress", walletAddress), + zap.String("amount", amount), + ) + + findErr := errors.NewWithError( + fmt.Errorf("failed to find payment by walletAddress and amount: %w", err), + errors.ErrInternalError, + ) + + if err == mongo.ErrNoDocuments { + return nil, findErr.SetType(errors.ErrNotFound) + } + + return nil, findErr + } + + return &payment, nil +}