package veli import ( "context" "errors" "fmt" "strconv" "strings" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" ) var ( ErrPlayerNotFound = errors.New("PLAYER_NOT_FOUND") ErrSessionExpired = errors.New("SESSION_EXPIRED") ErrInsufficientBalance = errors.New("INSUFFICIENT_BALANCE") ErrDuplicateTransaction = errors.New("DUPLICATE_TRANSACTION") ) func (c *Client) GetProviders(ctx context.Context, req domain.ProviderRequest) (*domain.ProviderResponse, error) { sigParams := map[string]string{"brandId": req.BrandID} if req.Page > 0 { sigParams["page"] = fmt.Sprintf("%d", req.Page) } if req.Size > 0 { sigParams["size"] = fmt.Sprintf("%d", req.Size) } var res domain.ProviderResponse err := c.post(ctx, "/game-lists/public/providers", req, sigParams, &res) return &res, err } func (c *Client) GetGames(ctx context.Context, req domain.GameListRequest) ([]domain.GameEntity, error) { sigParams := map[string]string{ "brandId": req.BrandID, "providerId": req.ProviderID, } var res struct { Items []domain.GameEntity `json:"items"` } err := c.post(ctx, "/game-lists/public/games", req, sigParams, &res) return res.Items, err } func (c *Client) StartGame(ctx context.Context, req domain.GameStartRequest) (*domain.GameStartResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, "gameId": req.GameID, "language": req.Language, "playerId": req.PlayerID, "currency": req.Currency, "deviceType": req.DeviceType, "country": req.Country, "ip": req.IP, "brandId": req.BrandID, } var res domain.GameStartResponse err := c.post(ctx, "/unified-api/public/start-game", req, sigParams, &res) return &res, err } func (c *Client) StartDemoGame(ctx context.Context, req domain.DemoGameRequest) (*domain.GameStartResponse, error) { sigParams := map[string]string{ "providerId": req.ProviderID, "gameId": req.GameID, "language": req.Language, "deviceType": req.DeviceType, "ip": req.IP, "brandId": req.BrandID, } var res domain.GameStartResponse err := c.post(ctx, "/unified-api/public/start-demo-game", req, sigParams, &res) return &res, err } func (c *Client) GetBalance(ctx context.Context, req domain.BalanceRequest) (*domain.BalanceResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, "playerId": req.PlayerID, "currency": req.Currency, "brandId": req.BrandID, } if req.GameID != "" { sigParams["gameId"] = req.GameID } var res domain.BalanceResponse err := c.post(ctx, "/balance", req, sigParams, &res) return &res, err } func (c *Client) ProcessBet(ctx context.Context, req domain.BetRequest) (*domain.BetResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, "playerId": req.PlayerID, "currency": req.Amount.Currency, "brandId": req.BrandID, "gameId": req.GameID, "roundId": req.RoundID, "transactionId": req.TransactionID, "correlationId": req.CorrelationID, } if req.GameType != "" { sigParams["gameType"] = req.GameType } if req.IsAdjustment { sigParams["isAdjustment"] = "true" } if req.JackpotID != "" { sigParams["jackpotId"] = req.JackpotID sigParams["jackpotContribution"] = fmt.Sprintf("%.2f", req.JackpotContribution) } var res domain.BetResponse err := c.post(ctx, "/bet", req, sigParams, &res) playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { return &domain.BetResponse{}, fmt.Errorf("invalid PlayerID: %w", err) } wallets, err := c.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return &domain.BetResponse{}, err } c.walletSvc.DeductFromWallet(ctx, wallets[0].ID, domain.Currency(req.Amount.Amount), domain.CustomerWalletType, domain.ValidInt64{}, domain.TRANSFER_DIRECT, fmt.Sprintf("Deducting %v from wallet for creating Veli Game Bet", req.Amount.Amount), ) return &res, err } func (c *Client) ProcessWin(ctx context.Context, req domain.WinRequest) (*domain.WinResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, "playerId": req.PlayerID, "currency": req.Amount.Currency, "brandId": req.BrandID, "gameId": req.GameID, "roundId": req.RoundID, "transactionId": req.TransactionID, "correlationId": req.CorrelationID, "winType": req.WinType, } if req.GameType != "" { sigParams["gameType"] = req.GameType } if req.RewardID != "" { sigParams["rewardId"] = req.RewardID } if req.IsCashOut { sigParams["isCashOut"] = "true" } var res domain.WinResponse err := c.post(ctx, "/win", req, sigParams, &res) playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { return &domain.WinResponse{}, fmt.Errorf("invalid PlayerID: %w", err) } wallets, err := c.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return &domain.WinResponse{}, err } c.walletSvc.AddToWallet(ctx, wallets[0].ID, domain.Currency(req.Amount.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Adding %v to wallet due to winning Veli Games bet", req.Amount), ) return &res, err } func (c *Client) ProcessCancel(ctx context.Context, req domain.CancelRequest) (*domain.CancelResponse, error) { sigParams := map[string]string{ "sessionId": req.SessionID, "providerId": req.ProviderID, "playerId": req.PlayerID, "brandId": req.BrandID, "gameId": req.GameID, "roundId": req.RoundID, "transactionId": req.TransactionID, "cancelType": req.CancelType, } if req.GameType != "" { sigParams["gameType"] = req.GameType } if req.CorrelationID != "" { sigParams["correlationId"] = req.CorrelationID } if req.RefTransactionID != "" { sigParams["refTransactionId"] = req.RefTransactionID } if req.AdjustmentRefund.Amount > 0 { sigParams["adjustmentRefundAmount"] = fmt.Sprintf("%.2f", req.AdjustmentRefund.Amount) sigParams["adjustmentRefundCurrency"] = req.AdjustmentRefund.Currency } var res domain.CancelResponse err := c.post(ctx, "/cancel", req, sigParams, &res) playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64) if err != nil { return &domain.CancelResponse{}, fmt.Errorf("invalid PlayerID: %w", err) } wallets, err := c.walletSvc.GetWalletsByUser(ctx, playerIDInt64) if err != nil { return &domain.CancelResponse{}, err } c.walletSvc.AddToWallet(ctx, wallets[0].ID, domain.Currency(req.AdjustmentRefund.Amount), domain.ValidInt64{}, domain.TRANSFER_DIRECT, domain.PaymentDetails{}, fmt.Sprintf("Adding %v to wallet due to cancelling virtual game bet", req.AdjustmentRefund.Amount), ) return &res, err } func (c *Client) GetGamingActivity(ctx context.Context, req domain.GamingActivityRequest) (*domain.GamingActivityResponse, error) { // Prepare signature parameters (sorted string map of non-nested fields) sigParams := map[string]string{ "fromDate": req.FromDate, "toDate": req.ToDate, "brandId": req.BrandID, } // Optional filters if req.ProviderID != "" { sigParams["providerId"] = req.ProviderID } if len(req.PlayerIDs) > 0 { sigParams["playerIds"] = strings.Join(req.PlayerIDs, ",") } if len(req.GameIDs) > 0 { sigParams["gameIds"] = strings.Join(req.GameIDs, ",") } if len(req.Currencies) > 0 { sigParams["currencies"] = strings.Join(req.Currencies, ",") } if req.Page > 0 { sigParams["page"] = fmt.Sprintf("%d", req.Page) } if req.Size > 0 { sigParams["size"] = fmt.Sprintf("%d", req.Size) } if req.ExcludeFreeWin != nil { sigParams["excludeFreeWin"] = fmt.Sprintf("%t", *req.ExcludeFreeWin) } var res domain.GamingActivityResponse err := c.post(ctx, "/report-api/public/gaming-activity", req, sigParams, &res) if err != nil { return nil, err } return &res, nil }