diff --git a/cmd/main.go b/cmd/main.go index ec66aeb..9f90784 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -153,7 +153,7 @@ func main() { virtualGameSvc := virtualgameservice.New(vitualGameRepo, *walletSvc, store, cfg, logger) aleaService := alea.NewAleaPlayService(vitualGameRepo, *walletSvc, cfg, logger) veliCLient := veli.NewClient(cfg, walletSvc) - veliVirtualGameService := veli.New(veliCLient, walletSvc, cfg) + veliVirtualGameService := veli.New(veliCLient, walletSvc, wallet.TransferStore(store), cfg) recommendationSvc := recommendation.NewService(recommendationRepo) chapaClient := chapa.NewClient(cfg.CHAPA_BASE_URL, cfg.CHAPA_SECRET_KEY) diff --git a/internal/domain/veli_games.go b/internal/domain/veli_games.go index 6f40841..3b86e83 100644 --- a/internal/domain/veli_games.go +++ b/internal/domain/veli_games.go @@ -136,6 +136,7 @@ type CancelRequest struct { CorrelationID string `json:"correlationId,omitempty"` ProviderID string `json:"providerId"` BrandID string `json:"brandId"` + IsAdjustment bool `json:"isAdjustment,omitempty"` AdjustmentRefund *struct { Amount float64 `json:"amount"` Currency string `json:"currency"` diff --git a/internal/services/virtualGame/veli/service.go b/internal/services/virtualGame/veli/service.go index 4c675cc..e0fa68b 100644 --- a/internal/services/virtualGame/veli/service.go +++ b/internal/services/virtualGame/veli/service.go @@ -19,16 +19,18 @@ var ( ) type service struct { - client *Client - walletSvc *wallet.Service - cfg *config.Config + client *Client + walletSvc *wallet.Service + transfetStore wallet.TransferStore + cfg *config.Config } -func New(client *Client, walletSvc *wallet.Service, cfg *config.Config) VeliVirtualGameService { +func New(client *Client, walletSvc *wallet.Service, transferStore wallet.TransferStore, cfg *config.Config) VeliVirtualGameService { return &service{ - client: client, - walletSvc: walletSvc, - cfg: cfg, + client: client, + walletSvc: walletSvc, + transfetStore: transferStore, + cfg: cfg, } } @@ -338,7 +340,7 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) ( // --- 1. Validate PlayerID --- playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { - return nil, fmt.Errorf("invalid PlayerID %s", req.PlayerID) + return nil, fmt.Errorf("invalid PlayerID %q", req.PlayerID) } // --- 2. Get player wallets --- @@ -358,18 +360,23 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) ( bonusBalance = float64(playerWallets[1].Balance) } - // --- 3. Refund handling --- + // --- 3. Determine refund amount based on IsAdjustment --- var refundAmount float64 - if req.AdjustmentRefund.Amount > 0 { + if req.IsAdjustment { + if req.AdjustmentRefund.Amount <= 0 { + return nil, fmt.Errorf("missing adjustmentRefund for adjustment cancel") + } refundAmount = req.AdjustmentRefund.Amount } else { - // If cancelType = CANCEL_BET and no explicit adjustmentRefund, - // we may need to look up the original bet transaction and refund that. - // TODO: implement transaction lookup if required by your domain. - return nil, fmt.Errorf("missing adjustmentRefund for CANCEL_BET") + // Regular cancel: fetch original bet amount if needed + originalTransfer, err := s.transfetStore.GetTransferByReference(ctx, req.RefTransactionID) + if err != nil { + return nil, fmt.Errorf("failed to get original bet for cancellation: %w", err) + } + refundAmount = float64(originalTransfer.Amount) } - // For now, we assume refund goes back fully to real wallet + // --- 4. Refund to wallet --- usedReal := refundAmount usedBonus := 0.0 @@ -392,7 +399,7 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) ( return nil, fmt.Errorf("failed to refund wallet: %w", err) } - // --- 4. Reload balances after refund --- + // --- 5. Reload balances after refund --- updatedWallets, err := s.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return nil, fmt.Errorf("failed to reload balances: %w", err) @@ -405,11 +412,11 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) ( bonusBalance = float64(updatedWallets[1].Balance) } - // --- 5. Build response --- + // --- 6. Build response --- res := &domain.CancelResponse{ WalletTransactionID: req.TransactionID, Real: domain.BalanceDetail{ - Currency: req.AdjustmentRefund.Currency, + Currency: "ETB", Amount: realBalance, }, UsedRealAmount: usedReal, @@ -418,7 +425,7 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) ( if bonusBalance > 0 { res.Bonus = &domain.BalanceDetail{ - Currency: req.AdjustmentRefund.Currency, + Currency: "ETB", Amount: bonusBalance, } } @@ -426,6 +433,12 @@ func (s *service) ProcessCancel(ctx context.Context, req domain.CancelRequest) ( return res, nil } +// Example helper to fetch original bet +// func (s *service) getOriginalBet(ctx context.Context, transactionID string) (*domain.BetRecord, error) { +// // TODO: implement actual lookup +// return &domain.BetRecord{Amount: 50}, nil +// } + func (s *service) GetGamingActivity(ctx context.Context, req domain.GamingActivityRequest) (*domain.GamingActivityResponse, error) { // --- Signature Params (flattened strings for signing) --- sigParams := map[string]any{ diff --git a/internal/web_server/handlers/virtual_games_hadlers.go b/internal/web_server/handlers/virtual_games_hadlers.go index 257b294..5351fee 100644 --- a/internal/web_server/handlers/virtual_games_hadlers.go +++ b/internal/web_server/handlers/virtual_games_hadlers.go @@ -110,7 +110,7 @@ func (h *Handler) HandlePlayerInfo(c *fiber.Ctx) error { } func (h *Handler) HandleBet(c *fiber.Ctx) error { - // Read the raw body to avoid parsing issues + // Read the raw body body := c.Body() if len(body) == 0 { return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ @@ -119,26 +119,11 @@ func (h *Handler) HandleBet(c *fiber.Ctx) error { }) } - // Try to identify the provider based on the request structure - provider, err := identifyBetProvider(body) - if err != nil { - return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ - Message: "Unrecognized request format", - Error: err.Error(), - }) - } - - switch provider { - case "veli": - var req domain.BetRequest - if err := json.Unmarshal(body, &req); err != nil { - return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ - Message: "Invalid Veli bet request", - Error: err.Error(), - }) - } - - res, err := h.veliVirtualGameSvc.ProcessBet(c.Context(), req) + // Try parsing as Veli bet request + var veliReq domain.BetRequest + if err := json.Unmarshal(body, &veliReq); err == nil && veliReq.SessionID != "" && veliReq.BrandID != "" { + // Process as Veli + res, err := h.veliVirtualGameSvc.ProcessBet(c.Context(), veliReq) if err != nil { if errors.Is(err, veli.ErrDuplicateTransaction) { return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{ @@ -152,17 +137,13 @@ func (h *Handler) HandleBet(c *fiber.Ctx) error { }) } return c.JSON(res) + } - case "popok": - var req domain.PopOKBetRequest - if err := json.Unmarshal(body, &req); err != nil { - return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ - Message: "Invalid PopOK bet request", - Error: err.Error(), - }) - } - - resp, err := h.virtualGameSvc.ProcessBet(c.Context(), &req) + // Try parsing as PopOK bet request + var popokReq domain.PopOKBetRequest + if err := json.Unmarshal(body, &popokReq); err == nil && popokReq.ExternalToken != "" { + // Process as PopOK + resp, err := h.virtualGameSvc.ProcessBet(c.Context(), &popokReq) if err != nil { code := fiber.StatusInternalServerError switch err.Error() { @@ -177,13 +158,13 @@ func (h *Handler) HandleBet(c *fiber.Ctx) error { }) } return c.JSON(resp) - - default: - return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ - Message: "Unsupported provider", - Error: "Request format doesn't match any supported provider", - }) } + + // If neither works + return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{ + Message: "Unsupported provider", + Error: "Request format doesn't match any supported provider", + }) } // identifyProvider examines the request body to determine the provider @@ -513,7 +494,7 @@ func (h *Handler) ListFavorites(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(games) } -func identifyBetProvider(body []byte) (string, error) { +func IdentifyBetProvider(body []byte) (string, error) { // Check for Veli signature fields var veliCheck struct { SessionID string `json:"sessionId"`