veli games error types and bonus balance fixes
This commit is contained in:
parent
2a41a2426c
commit
e8c2213d30
|
|
@ -149,12 +149,12 @@ func main() {
|
||||||
cfg,
|
cfg,
|
||||||
)
|
)
|
||||||
|
|
||||||
marketSettingRepo := repository.NewMarketSettingStore(store)
|
marketSettingRepo := repository.NewMarketSettingStore(store)
|
||||||
|
|
||||||
if err := marketSettingRepo.EnsureAllMarketSettingsExist(context.Background()); err != nil {
|
if err := marketSettingRepo.EnsureAllMarketSettingsExist(context.Background()); err != nil {
|
||||||
log.Fatalf("failed to ensure market settings: %v", err)
|
log.Fatalf("failed to ensure market settings: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
oddsSvc := odds.New(
|
oddsSvc := odds.New(
|
||||||
repository.NewOddStore(store),
|
repository.NewOddStore(store),
|
||||||
marketSettingRepo,
|
marketSettingRepo,
|
||||||
|
|
@ -251,7 +251,7 @@ func main() {
|
||||||
virtualGameSvc := virtualgameservice.New(virtualGamesRepo, *walletSvc, store, cfg, logger)
|
virtualGameSvc := virtualgameservice.New(virtualGamesRepo, *walletSvc, store, cfg, logger)
|
||||||
aleaService := alea.NewAleaPlayService(virtualGamesRepo, *walletSvc, cfg, logger)
|
aleaService := alea.NewAleaPlayService(virtualGamesRepo, *walletSvc, cfg, logger)
|
||||||
veliCLient := veli.NewClient(cfg, walletSvc)
|
veliCLient := veli.NewClient(cfg, walletSvc)
|
||||||
veliVirtualGameService := veli.New(virtualGameSvc, virtualGamesRepo, veliCLient, walletSvc, repository.NewTransferStore(store), domain.MongoDBLogger, cfg)
|
veliVirtualGameService := veli.New(virtualGameSvc, virtualGamesRepo, *store, veliCLient, walletSvc, repository.NewTransferStore(store), domain.MongoDBLogger, cfg)
|
||||||
orchestrationSvc := orchestration.New(
|
orchestrationSvc := orchestration.New(
|
||||||
virtualGameSvc,
|
virtualGameSvc,
|
||||||
virtualGamesRepo,
|
virtualGamesRepo,
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ RETURNING id,
|
||||||
status,
|
status,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at;
|
updated_at;
|
||||||
|
|
||||||
-- name: GetVirtualGameTransactionByExternalID :one
|
-- name: GetVirtualGameTransactionByExternalID :one
|
||||||
SELECT id,
|
SELECT id,
|
||||||
session_id,
|
session_id,
|
||||||
|
|
@ -180,6 +181,7 @@ SELECT id,
|
||||||
updated_at
|
updated_at
|
||||||
FROM virtual_game_transactions
|
FROM virtual_game_transactions
|
||||||
WHERE external_transaction_id = $1;
|
WHERE external_transaction_id = $1;
|
||||||
|
|
||||||
-- name: UpdateVirtualGameTransactionStatus :exec
|
-- name: UpdateVirtualGameTransactionStatus :exec
|
||||||
UPDATE virtual_game_transactions
|
UPDATE virtual_game_transactions
|
||||||
SET status = $2,
|
SET status = $2,
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ var (
|
||||||
type Service struct {
|
type Service struct {
|
||||||
virtualGameSvc virtualgameservice.VirtualGameService
|
virtualGameSvc virtualgameservice.VirtualGameService
|
||||||
repo repository.VirtualGameRepository
|
repo repository.VirtualGameRepository
|
||||||
|
genRepo repository.Store
|
||||||
client *Client
|
client *Client
|
||||||
walletSvc *wallet.Service
|
walletSvc *wallet.Service
|
||||||
transfetStore ports.TransferStore
|
transfetStore ports.TransferStore
|
||||||
|
|
@ -40,6 +41,7 @@ type Service struct {
|
||||||
func New(
|
func New(
|
||||||
virtualGameSvc virtualgameservice.VirtualGameService,
|
virtualGameSvc virtualgameservice.VirtualGameService,
|
||||||
repo repository.VirtualGameRepository,
|
repo repository.VirtualGameRepository,
|
||||||
|
genRepo repository.Store,
|
||||||
client *Client,
|
client *Client,
|
||||||
walletSvc *wallet.Service,
|
walletSvc *wallet.Service,
|
||||||
transferStore ports.TransferStore,
|
transferStore ports.TransferStore,
|
||||||
|
|
@ -49,6 +51,7 @@ func New(
|
||||||
return &Service{
|
return &Service{
|
||||||
virtualGameSvc: virtualGameSvc,
|
virtualGameSvc: virtualGameSvc,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
|
genRepo: genRepo,
|
||||||
client: client,
|
client: client,
|
||||||
walletSvc: walletSvc,
|
walletSvc: walletSvc,
|
||||||
transfetStore: transferStore,
|
transfetStore: transferStore,
|
||||||
|
|
@ -160,6 +163,15 @@ func (s *Service) StartGame(ctx context.Context, req domain.GameStartRequest) (*
|
||||||
// return nil, fmt.Errorf("provider %s is disabled", req.ProviderID)
|
// return nil, fmt.Errorf("provider %s is disabled", req.ProviderID)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid PlayerID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := s.genRepo.GetUserByID(ctx, playerIDInt64); err != nil {
|
||||||
|
return nil, ErrPlayerNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// 2. Prepare signature params
|
// 2. Prepare signature params
|
||||||
sigParams := map[string]any{
|
sigParams := map[string]any{
|
||||||
"sessionId": req.SessionID,
|
"sessionId": req.SessionID,
|
||||||
|
|
@ -180,10 +192,10 @@ func (s *Service) StartGame(ctx context.Context, req domain.GameStartRequest) (*
|
||||||
return nil, fmt.Errorf("failed to start game with provider %s: %w", req.ProviderID, err)
|
return nil, fmt.Errorf("failed to start game with provider %s: %w", req.ProviderID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
// playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, fmt.Errorf("invalid PlayerID: %w", err)
|
// return nil, fmt.Errorf("invalid PlayerID: %w", err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
session := &domain.VirtualGameSession{
|
session := &domain.VirtualGameSession{
|
||||||
UserID: playerIDInt64,
|
UserID: playerIDInt64,
|
||||||
|
|
@ -243,6 +255,15 @@ func (s *Service) GetBalance(ctx context.Context, req domain.BalanceRequest) (*d
|
||||||
// return nil, fmt.Errorf("PLAYER_NOT_FOUND: no wallet found for player %s", req.PlayerID)
|
// return nil, fmt.Errorf("PLAYER_NOT_FOUND: no wallet found for player %s", req.PlayerID)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// playerIDInt64, err := strconv.ParseInt(req.PlayerID, 10, 64)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("invalid PlayerID: %w", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
if _, err := s.genRepo.GetUserByID(ctx, playerIDInt64); err != nil {
|
||||||
|
return nil, ErrPlayerNotFound
|
||||||
|
}
|
||||||
|
|
||||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read user wallets")
|
return nil, fmt.Errorf("failed to read user wallets")
|
||||||
|
|
@ -285,13 +306,26 @@ func (s *Service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domai
|
||||||
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
|
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := s.genRepo.GetUserByID(ctx, playerIDInt64); err != nil {
|
||||||
|
return nil, ErrPlayerNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
existingTx, err := s.repo.GetVirtualGameTransactionByExternalID(ctx, req.TransactionID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed checking idempotency: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existingTx != nil {
|
||||||
|
// Idempotent return — already processed
|
||||||
|
return nil, fmt.Errorf("DUPLICATE_TRANSACTION")
|
||||||
|
}
|
||||||
|
|
||||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read user wallets")
|
return nil, fmt.Errorf("failed to read user wallets")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bonusBalance := float64(wallet.StaticBalance.Float32())
|
||||||
bonusBalance := float64(wallet.StaticBalance.Float32())
|
|
||||||
|
|
||||||
// --- 4. Check sufficient balance ---
|
// --- 4. Check sufficient balance ---
|
||||||
if float64(wallet.RegularBalance.Float32()) < req.Amount.Amount {
|
if float64(wallet.RegularBalance.Float32()) < req.Amount.Amount {
|
||||||
|
|
@ -321,11 +355,26 @@ func (s *Service) ProcessBet(ctx context.Context, req domain.BetRequest) (*domai
|
||||||
UsedBonusAmount: 0,
|
UsedBonusAmount: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
if bonusBalance > 0 {
|
// if bonusBalance > 0 {
|
||||||
res.Bonus = &domain.BalanceDetail{
|
// res.Bonus = &domain.BalanceDetail{
|
||||||
Currency: req.Amount.Currency,
|
// Currency: req.Amount.Currency,
|
||||||
Amount: bonusBalance,
|
// Amount: bonusBalance,
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
if err = s.repo.CreateVirtualGameTransaction(ctx, &domain.VirtualGameTransaction{
|
||||||
|
UserID: playerIDInt64,
|
||||||
|
Provider: req.ProviderID,
|
||||||
|
GameID: req.GameID,
|
||||||
|
WalletID: wallet.RegularID,
|
||||||
|
TransactionType: "BET",
|
||||||
|
Amount: int64(req.Amount.Amount),
|
||||||
|
Currency: req.Amount.Currency,
|
||||||
|
ExternalTransactionID: req.TransactionID,
|
||||||
|
Status: "pending",
|
||||||
|
GameRoundID: req.RoundID,
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to log virtual game transaction: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|
@ -338,6 +387,10 @@ func (s *Service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
|
||||||
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
|
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %s", req.PlayerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := s.genRepo.GetUserByID(ctx, playerIDInt64); err != nil {
|
||||||
|
return nil, ErrPlayerNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// --- 2. Get player wallets ---
|
// --- 2. Get player wallets ---
|
||||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -346,7 +399,7 @@ func (s *Service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
|
||||||
|
|
||||||
// --- 3. Convert balances safely using Float32() ---
|
// --- 3. Convert balances safely using Float32() ---
|
||||||
realBalance := float64(wallet.RegularBalance.Float32())
|
realBalance := float64(wallet.RegularBalance.Float32())
|
||||||
bonusBalance := float64(wallet.StaticBalance.Float32())
|
// bonusBalance := float64(wallet.StaticBalance.Float32())
|
||||||
|
|
||||||
// --- 4. Apply winnings ---
|
// --- 4. Apply winnings ---
|
||||||
winAmount := req.Amount.Amount
|
winAmount := req.Amount.Amount
|
||||||
|
|
@ -378,12 +431,12 @@ func (s *Service) ProcessWin(ctx context.Context, req domain.WinRequest) (*domai
|
||||||
UsedBonusAmount: usedBonus,
|
UsedBonusAmount: usedBonus,
|
||||||
}
|
}
|
||||||
|
|
||||||
if bonusBalance > 0 {
|
// if bonusBalance > 0 {
|
||||||
res.Bonus = &domain.BalanceDetail{
|
// res.Bonus = &domain.BalanceDetail{
|
||||||
Currency: req.Amount.Currency,
|
// Currency: req.Amount.Currency,
|
||||||
Amount: bonusBalance,
|
// Amount: bonusBalance,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
@ -395,6 +448,10 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
||||||
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %q", req.PlayerID)
|
return nil, fmt.Errorf("BAD_REQUEST: invalid PlayerID %q", req.PlayerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := s.genRepo.GetUserByID(ctx, playerIDInt64); err != nil {
|
||||||
|
return nil, ErrPlayerNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// --- 2. Get player wallets ---
|
// --- 2. Get player wallets ---
|
||||||
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
wallet, err := s.walletSvc.GetCustomerWallet(ctx, playerIDInt64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -403,7 +460,7 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
||||||
|
|
||||||
// --- 3. Convert balances using Float32() ---
|
// --- 3. Convert balances using Float32() ---
|
||||||
realBalance := float64(wallet.RegularBalance.Float32())
|
realBalance := float64(wallet.RegularBalance.Float32())
|
||||||
bonusBalance := float64(wallet.StaticBalance.Float32())
|
// bonusBalance := float64(wallet.StaticBalance.Float32())
|
||||||
|
|
||||||
// --- 4. Determine refund amount ---
|
// --- 4. Determine refund amount ---
|
||||||
var refundAmount float64
|
var refundAmount float64
|
||||||
|
|
@ -454,12 +511,12 @@ func (s *Service) ProcessCancel(ctx context.Context, req domain.CancelRequest) (
|
||||||
UsedBonusAmount: usedBonus,
|
UsedBonusAmount: usedBonus,
|
||||||
}
|
}
|
||||||
|
|
||||||
if bonusBalance > 0 {
|
// if bonusBalance > 0 {
|
||||||
res.Bonus = &domain.BalanceDetail{
|
// res.Bonus = &domain.BalanceDetail{
|
||||||
Currency: req.AdjustmentRefund.Currency,
|
// Currency: req.AdjustmentRefund.Currency,
|
||||||
Amount: bonusBalance,
|
// Amount: bonusBalance,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -312,14 +312,6 @@ func (h *Handler) HandlePlayerInfo(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) HandleBet(c *fiber.Ctx) error {
|
func (h *Handler) HandleBet(c *fiber.Ctx) error {
|
||||||
// userID := c.Locals("user_id")
|
|
||||||
// fmt.Printf("\n\nBet User ID is%v\n\n",userID)
|
|
||||||
// if userID == "" {
|
|
||||||
// return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
||||||
// Message: "Failed to process Bet request",
|
|
||||||
// Error: "Invalid user identification",
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// Read the raw body
|
// Read the raw body
|
||||||
body := c.Body()
|
body := c.Body()
|
||||||
if len(body) == 0 {
|
if len(body) == 0 {
|
||||||
|
|
@ -354,8 +346,18 @@ func (h *Handler) HandleBet(c *fiber.Ctx) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
||||||
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
Message: "Duplicate transaction",
|
// Message: "Duplicate transaction",
|
||||||
Error: "DUPLICATE_TRANSACTION",
|
Error: veli.ErrDuplicateTransaction.Error(),
|
||||||
|
})
|
||||||
|
} else if errors.Is(err, veli.ErrInsufficientBalance) {
|
||||||
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
|
// Message: "Wallet balance is insufficient",
|
||||||
|
Error: veli.ErrInsufficientBalance.Error(),
|
||||||
|
})
|
||||||
|
} else if errors.Is(err, veli.ErrPlayerNotFound) {
|
||||||
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
|
// Message: "User not found",
|
||||||
|
Error: veli.ErrPlayerNotFound.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||||
|
|
@ -471,8 +473,13 @@ func (h *Handler) HandleWin(c *fiber.Ctx) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
||||||
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
Message: "Duplicate transaction",
|
// Message: "Duplicate transaction",
|
||||||
Error: "DUPLICATE_TRANSACTION",
|
Error: veli.ErrDuplicateTransaction.Error(),
|
||||||
|
})
|
||||||
|
} else if errors.Is(err, veli.ErrPlayerNotFound) {
|
||||||
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
|
// Message: "Duplicate transaction",
|
||||||
|
Error: veli.ErrPlayerNotFound.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||||
|
|
@ -543,8 +550,13 @@ func (h *Handler) HandleCancel(c *fiber.Ctx) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
||||||
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
Message: "Duplicate transaction",
|
// Message: "Duplicate transaction",
|
||||||
Error: "DUPLICATE_TRANSACTION",
|
Error: veli.ErrDuplicateTransaction.Error(),
|
||||||
|
})
|
||||||
|
} else if errors.Is(err, veli.ErrPlayerNotFound) {
|
||||||
|
return c.Status(fiber.StatusConflict).JSON(domain.ErrorResponse{
|
||||||
|
// Message: "User not found",
|
||||||
|
Error: veli.ErrPlayerNotFound.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user