added full logic for webhook Alchemy

This commit is contained in:
Pasha 2025-07-21 18:03:53 +03:00
parent ca24a9c1f2
commit bdd41ee126
3 changed files with 54 additions and 5 deletions

@ -29,6 +29,8 @@ type Payment struct {
Запрос будет отправляться по протоколу GRPC
*/
CallbackHostGRPC []string `json:"callbackHostGrpc" bson:"callbackHostGrpc"`
WalletAddress string // for crypto
}
func (p *Payment) Sanitize() *Payment {

@ -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)
}

@ -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 <FindByWalletAddressAndAmount> of <PaymentRepository>",
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
}