398 lines
12 KiB
Go
398 lines
12 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/services/virtualGame/veli"
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
// GetProviders godoc
|
|
// @Summary Get game providers
|
|
// @Description Retrieves the list of VeliGames providers
|
|
// @Tags Virtual Games - VeliGames
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body domain.ProviderRequest true "Brand ID and paging options"
|
|
// @Success 200 {object} domain.Response{data=[]domain.ProviderResponse}
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 401 {object} domain.ErrorResponse
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/veli/providers [post]
|
|
func (h *Handler) GetProviders(c *fiber.Ctx) error {
|
|
var req domain.ProviderRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Failed to retrieve providers",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if req.BrandID == "" {
|
|
req.BrandID = h.Cfg.VeliGames.BrandID // default
|
|
}
|
|
res, err := h.veliVirtualGameSvc.GetProviders(context.Background(), req)
|
|
if err != nil {
|
|
log.Println("GetProviders error:", err)
|
|
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
|
Message: "Failed to retrieve providers",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
Message: "Providers retrieved successfully",
|
|
Data: res,
|
|
StatusCode: 200,
|
|
Success: true,
|
|
})
|
|
}
|
|
|
|
// GetGamesByProvider godoc
|
|
// @Summary Get games by provider
|
|
// @Description Retrieves games for the specified provider
|
|
// @Tags Virtual Games - VeliGames
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body domain.GameListRequest true "Brand and Provider ID"
|
|
// @Success 200 {object} domain.Response
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 502 {object} domain.ErrorResponse
|
|
// @Router /api/v1/veli/games-list [post]
|
|
func (h *Handler) GetGamesByProvider(c *fiber.Ctx) error {
|
|
var req domain.GameListRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Default brand if not provided
|
|
if req.BrandID == "" {
|
|
req.BrandID = h.Cfg.VeliGames.BrandID
|
|
}
|
|
|
|
res, err := h.veliVirtualGameSvc.GetGames(context.Background(), req)
|
|
if err != nil {
|
|
log.Println("GetGames error:", err)
|
|
|
|
// Handle provider disabled case specifically
|
|
if strings.Contains(err.Error(), "is disabled") {
|
|
return c.Status(fiber.StatusForbidden).JSON(domain.ErrorResponse{
|
|
Message: "Provider is disabled",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Fallback for other errors
|
|
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
|
Message: "Failed to retrieve games",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
Message: "Games retrieved successfully",
|
|
Data: res,
|
|
StatusCode: fiber.StatusOK,
|
|
Success: true,
|
|
})
|
|
}
|
|
|
|
|
|
// StartGame godoc
|
|
// @Summary Start a real game session
|
|
// @Description Starts a real VeliGames session with the given player and game info
|
|
// @Tags Virtual Games - VeliGames
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body domain.GameStartRequest true "Start game input"
|
|
// @Success 200 {object} domain.Response{data=domain.GameStartResponse}
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 502 {object} domain.ErrorResponse
|
|
// @Router /api/v1/veli/start-game [post]
|
|
func (h *Handler) StartGame(c *fiber.Ctx) error {
|
|
userId, ok := c.Locals("user_id").(int64)
|
|
if !ok {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(domain.ErrorResponse{
|
|
Error: "missing user id",
|
|
Message: "Unauthorized",
|
|
})
|
|
}
|
|
|
|
var req domain.GameStartRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Attach user ID to request
|
|
req.PlayerID = fmt.Sprintf("%d", userId)
|
|
|
|
// Default brand if not provided
|
|
if req.BrandID == "" {
|
|
req.BrandID = h.Cfg.VeliGames.BrandID
|
|
}
|
|
|
|
res, err := h.veliVirtualGameSvc.StartGame(context.Background(), req)
|
|
if err != nil {
|
|
log.Println("StartGame error:", err)
|
|
|
|
// Handle provider disabled case specifically
|
|
if strings.Contains(err.Error(), "is disabled") {
|
|
return c.Status(fiber.StatusForbidden).JSON(domain.ErrorResponse{
|
|
Message: "Provider is disabled",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Fallback for other errors
|
|
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
|
Message: "Failed to start game",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
Message: "Game started successfully",
|
|
Data: res,
|
|
StatusCode: fiber.StatusOK,
|
|
Success: true,
|
|
})
|
|
}
|
|
|
|
|
|
// StartDemoGame godoc
|
|
// @Summary Start a demo game session
|
|
// @Description Starts a demo session of the specified game (must support demo mode)
|
|
// @Tags Virtual Games - VeliGames
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body domain.DemoGameRequest true "Start demo game input"
|
|
// @Success 200 {object} domain.Response{data=domain.GameStartResponse}
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 502 {object} domain.ErrorResponse
|
|
// @Router /api/v1/veli/start-demo-game [post]
|
|
func (h *Handler) StartDemoGame(c *fiber.Ctx) error {
|
|
var req domain.DemoGameRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Default brand if not provided
|
|
if req.BrandID == "" {
|
|
req.BrandID = h.Cfg.VeliGames.BrandID
|
|
}
|
|
|
|
res, err := h.veliVirtualGameSvc.StartDemoGame(context.Background(), req)
|
|
if err != nil {
|
|
log.Println("StartDemoGame error:", err)
|
|
|
|
// Handle provider disabled case specifically
|
|
if strings.Contains(err.Error(), "is disabled") {
|
|
return c.Status(fiber.StatusForbidden).JSON(domain.ErrorResponse{
|
|
Message: "Provider is disabled",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Fallback for other errors
|
|
return c.Status(fiber.StatusBadGateway).JSON(domain.ErrorResponse{
|
|
Message: "Failed to start demo game",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
Message: "Demo game started successfully",
|
|
Data: res,
|
|
StatusCode: fiber.StatusOK,
|
|
Success: true,
|
|
})
|
|
}
|
|
|
|
|
|
func (h *Handler) GetBalance(c *fiber.Ctx) error {
|
|
var req domain.BalanceRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Optionally verify signature here...
|
|
|
|
balance, err := h.veliVirtualGameSvc.GetBalance(c.Context(), req)
|
|
if err != nil {
|
|
// return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Failed to retrieve balance",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.JSON(balance)
|
|
}
|
|
|
|
func (h *Handler) PlaceBet(c *fiber.Ctx) error {
|
|
var req domain.BetRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
// Signature check optional here
|
|
|
|
res, err := h.veliVirtualGameSvc.ProcessBet(c.Context(), req)
|
|
if err != nil {
|
|
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
|
return fiber.NewError(fiber.StatusConflict, "DUPLICATE_TRANSACTION")
|
|
}
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Failed to process bet",
|
|
Error: err.Error(),
|
|
})
|
|
// return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
|
}
|
|
|
|
return c.JSON(res)
|
|
}
|
|
|
|
func (h *Handler) RegisterWin(c *fiber.Ctx) error {
|
|
var req domain.WinRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
res, err := h.veliVirtualGameSvc.ProcessWin(c.Context(), req)
|
|
if err != nil {
|
|
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
|
return fiber.NewError(fiber.StatusConflict, "DUPLICATE_TRANSACTION")
|
|
}
|
|
// return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to process win",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.JSON(res)
|
|
}
|
|
|
|
func (h *Handler) CancelTransaction(c *fiber.Ctx) error {
|
|
var req domain.CancelRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
// return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request body",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
res, err := h.veliVirtualGameSvc.ProcessCancel(c.Context(), req)
|
|
if err != nil {
|
|
if errors.Is(err, veli.ErrDuplicateTransaction) {
|
|
return fiber.NewError(fiber.StatusConflict, "DUPLICATE_TRANSACTION")
|
|
}
|
|
// return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Failed to process cancel",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.JSON(res)
|
|
}
|
|
|
|
// GetGamingActivity godoc
|
|
// @Summary Get Veli Gaming Activity
|
|
// @Description Retrieves successfully processed gaming activity transactions (BET, WIN, CANCEL) from Veli Games
|
|
// @Tags Virtual Games - VeliGames
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body domain.GamingActivityRequest true "Gaming Activity Request"
|
|
// @Success 200 {object} domain.Response{data=domain.GamingActivityResponse}
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/veli/gaming-activity [post]
|
|
func (h *Handler) GetGamingActivity(c *fiber.Ctx) error {
|
|
var req domain.GamingActivityRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request payload",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
resp, err := h.veliVirtualGameSvc.GetGamingActivity(c.Context(), req)
|
|
if err != nil {
|
|
log.Println("GetGamingActivity error:", err)
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to retrieve gaming activity",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
Message: "Gaming activity retrieved successfully",
|
|
Data: resp,
|
|
StatusCode: fiber.StatusOK,
|
|
Success: true,
|
|
})
|
|
}
|
|
|
|
// GetHugeWins godoc
|
|
// @Summary Get Veli Huge Wins
|
|
// @Description Retrieves huge win transactions based on brand configuration (e.g. win > 10000 USD or 100x bet)
|
|
// @Tags Virtual Games - VeliGames
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body domain.HugeWinsRequest true "Huge Wins Request"
|
|
// @Success 200 {object} domain.Response{data=domain.HugeWinsResponse}
|
|
// @Failure 400 {object} domain.ErrorResponse
|
|
// @Failure 500 {object} domain.ErrorResponse
|
|
// @Router /api/v1/veli/huge-wins [post]
|
|
func (h *Handler) GetHugeWins(c *fiber.Ctx) error {
|
|
var req domain.HugeWinsRequest
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(domain.ErrorResponse{
|
|
Message: "Invalid request payload",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
resp, err := h.veliVirtualGameSvc.GetHugeWins(c.Context(), req)
|
|
if err != nil {
|
|
log.Println("GetHugeWins error:", err)
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: "Failed to retrieve huge wins",
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
|
|
return c.Status(fiber.StatusOK).JSON(domain.Response{
|
|
Message: "Huge wins retrieved successfully",
|
|
Data: resp,
|
|
StatusCode: fiber.StatusOK,
|
|
Success: true,
|
|
})
|
|
}
|