PopOK callback fix + API credentials
This commit is contained in:
parent
2f593c8430
commit
2f2ba65abd
2
go.mod
2
go.mod
|
|
@ -72,6 +72,6 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/resend/resend-go/v2 v2.20.0 // indirect
|
||||
github.com/resend/resend-go/v2 v2.20.0 // direct
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -260,7 +260,11 @@ func (c *Config) loadEnv() error {
|
|||
if c.ADRO_SMS_HOST_URL == "" {
|
||||
c.ADRO_SMS_HOST_URL = "https://api.afrosms.com"
|
||||
}
|
||||
|
||||
popOKClientID := os.Getenv("POPOK_CLIENT_ID")
|
||||
|
||||
popOKPlatform := os.Getenv("POPOK_PLATFORM")
|
||||
|
||||
if popOKClientID == "" {
|
||||
return ErrInvalidPopOKClientID
|
||||
}
|
||||
|
|
@ -285,6 +289,7 @@ func (c *Config) loadEnv() error {
|
|||
SecretKey: popOKSecretKey,
|
||||
BaseURL: popOKBaseURL,
|
||||
CallbackURL: popOKCallbackURL,
|
||||
Platform: popOKPlatform,
|
||||
}
|
||||
betToken := os.Getenv("BET365_TOKEN")
|
||||
if betToken == "" {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ type VirtualGame struct {
|
|||
MinBet float64 `json:"min_bet"`
|
||||
MaxBet float64 `json:"max_bet"`
|
||||
Volatility string `json:"volatility"`
|
||||
IsActive bool `json:"is_active"`
|
||||
IsActive bool `json:"is_active"`
|
||||
RTP float64 `json:"rtp"`
|
||||
IsFeatured bool `json:"is_featured"`
|
||||
PopularityScore int `json:"popularity_score"`
|
||||
|
|
@ -39,17 +39,18 @@ type VirtualGameSession struct {
|
|||
}
|
||||
|
||||
type VirtualGameTransaction struct {
|
||||
ID int64 `json:"id"`
|
||||
SessionID int64 `json:"session_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
TransactionType string `json:"transaction_type"` // BET, WIN, REFUND, CASHOUT, etc.
|
||||
Amount int64 `json:"amount"` // Always in cents
|
||||
Currency string `json:"currency"`
|
||||
ExternalTransactionID string `json:"external_transaction_id"`
|
||||
Status string `json:"status"` // PENDING, COMPLETED, FAILED
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID int64 `json:"id"`
|
||||
SessionID int64 `json:"session_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
WalletID int64 `json:"wallet_id"`
|
||||
TransactionType string `json:"transaction_type"` // BET, WIN, REFUND, CASHOUT, etc.
|
||||
Amount int64 `json:"amount"` // Always in cents
|
||||
Currency string `json:"currency"`
|
||||
ExternalTransactionID string `json:"external_transaction_id"`
|
||||
ReferenceTransactionID string `json:"reference_transaction_id"`
|
||||
Status string `json:"status"` // PENDING, COMPLETED, FAILED
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// Alea Play specific fields
|
||||
GameRoundID string `json:"game_round_id"` // Round identifier
|
||||
|
|
@ -87,6 +88,7 @@ type PopOKConfig struct {
|
|||
SecretKey string
|
||||
BaseURL string
|
||||
CallbackURL string
|
||||
Platform string
|
||||
}
|
||||
|
||||
type PopOKCallback struct {
|
||||
|
|
@ -99,6 +101,61 @@ type PopOKCallback struct {
|
|||
Signature string `json:"signature"` // HMAC-SHA256 signature for verification
|
||||
}
|
||||
|
||||
type PopOKPlayerInfoRequest struct {
|
||||
ExternalToken string `json:"externalToken"`
|
||||
}
|
||||
|
||||
type PopOKPlayerInfoResponse struct {
|
||||
Country string `json:"country"`
|
||||
Currency string `json:"currency"`
|
||||
Balance float64 `json:"balance"`
|
||||
PlayerID string `json:"playerId"`
|
||||
}
|
||||
|
||||
type PopOKBetRequest struct {
|
||||
ExternalToken string `json:"externalToken"`
|
||||
PlayerID string `json:"playerId"`
|
||||
GameID string `json:"gameId"`
|
||||
TransactionID string `json:"transactionId"`
|
||||
Amount float64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
}
|
||||
|
||||
type PopOKBetResponse struct {
|
||||
TransactionID string `json:"transactionId"`
|
||||
ExternalTrxID string `json:"externalTrxId"`
|
||||
Balance float64 `json:"balance"`
|
||||
}
|
||||
|
||||
// domain/popok.go
|
||||
type PopOKWinRequest struct {
|
||||
ExternalToken string `json:"externalToken"`
|
||||
PlayerID string `json:"playerId"`
|
||||
GameID string `json:"gameId"`
|
||||
TransactionID string `json:"transactionId"`
|
||||
Amount float64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
}
|
||||
|
||||
type PopOKWinResponse struct {
|
||||
TransactionID string `json:"transactionId"`
|
||||
ExternalTrxID string `json:"externalTrxId"`
|
||||
Balance float64 `json:"balance"`
|
||||
}
|
||||
|
||||
type PopOKCancelRequest struct {
|
||||
ExternalToken string `json:"externalToken"`
|
||||
PlayerID string `json:"playerId"`
|
||||
GameID string `json:"gameId"`
|
||||
TransactionID string `json:"transactionId"`
|
||||
}
|
||||
|
||||
type PopOKCancelResponse struct {
|
||||
TransactionID string `json:"transactionId"`
|
||||
ExternalTrxID string `json:"externalTrxId"`
|
||||
Balance float64 `json:"balance"`
|
||||
}
|
||||
|
||||
type AleaPlayCallback struct {
|
||||
EventID string `json:"event_id"`
|
||||
TransactionID string `json:"transaction_id"`
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ type VirtualGameRepository interface {
|
|||
CreateVirtualGameTransaction(ctx context.Context, tx *domain.VirtualGameTransaction) error
|
||||
GetVirtualGameTransactionByExternalID(ctx context.Context, externalID string) (*domain.VirtualGameTransaction, error)
|
||||
UpdateVirtualGameTransactionStatus(ctx context.Context, id int64, status string) error
|
||||
// WithTransaction(ctx context.Context, fn func(ctx context.Context) error) error
|
||||
|
||||
GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
}
|
||||
|
|
@ -151,3 +152,27 @@ func (r *VirtualGameRepo) GetGameCounts(ctx context.Context, filter domain.Repor
|
|||
|
||||
return total, active, inactive, nil
|
||||
}
|
||||
|
||||
// func (r *VirtualGameRepo) WithTransaction(ctx context.Context, fn func(ctx context.Context) error) error {
|
||||
// _, tx, err := r.store.BeginTx(ctx)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// txCtx := context.WithValue(ctx, contextTxKey, tx)
|
||||
|
||||
// defer func() {
|
||||
// if p := recover(); p != nil {
|
||||
// tx.Rollback(ctx)
|
||||
// panic(p)
|
||||
// }
|
||||
// }()
|
||||
|
||||
// err = fn(txCtx)
|
||||
// if err != nil {
|
||||
// tx.Rollback(ctx)
|
||||
// return err
|
||||
// }
|
||||
|
||||
// return tx.Commit(ctx)
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ import (
|
|||
type VirtualGameService interface {
|
||||
GenerateGameLaunchURL(ctx context.Context, userID int64, gameID, currency, mode string) (string, error)
|
||||
HandleCallback(ctx context.Context, callback *domain.PopOKCallback) error
|
||||
ProcessBet(ctx context.Context, req *domain.PopOKBetRequest) (*domain.PopOKBetResponse, error)
|
||||
GetPlayerInfo(ctx context.Context, req *domain.PopOKPlayerInfoRequest) (*domain.PopOKPlayerInfoResponse, error)
|
||||
ProcessWin(ctx context.Context, req *domain.PopOKWinRequest) (*domain.PopOKWinResponse, error)
|
||||
ProcessCancel(ctx context.Context, req *domain.PopOKCancelRequest) (*domain.PopOKCancelResponse, error)
|
||||
|
||||
GetGameCounts(ctx context.Context, filter domain.ReportFilter) (total, active, inactive int64, err error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ import (
|
|||
)
|
||||
|
||||
type service struct {
|
||||
repo repository.VirtualGameRepository
|
||||
walletSvc wallet.Service
|
||||
store *repository.Store
|
||||
repo repository.VirtualGameRepository
|
||||
walletSvc wallet.Service
|
||||
store *repository.Store
|
||||
// virtualGameStore repository.VirtualGameRepository
|
||||
config *config.Config
|
||||
logger *slog.Logger
|
||||
config *config.Config
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func New(repo repository.VirtualGameRepository, walletSvc wallet.Service, store *repository.Store, cfg *config.Config, logger *slog.Logger) VirtualGameService {
|
||||
|
|
@ -60,11 +60,18 @@ func (s *service) GenerateGameLaunchURL(ctx context.Context, userID int64, gameI
|
|||
}
|
||||
|
||||
params := fmt.Sprintf(
|
||||
"client_id=%s&game_id=%s¤cy=%s&lang=en&mode=%s&token=%s",
|
||||
s.config.PopOK.ClientID, gameID, currency, mode, token,
|
||||
"partnerId=%s&gameId=%s&gameMode=%s&lang=en&platform=%s&externalToken=%s",
|
||||
s.config.PopOK.ClientID, gameID, mode, s.config.PopOK.Platform, token,
|
||||
)
|
||||
signature := s.generateSignature(params)
|
||||
return fmt.Sprintf("%s/game/launch?%s&signature=%s", s.config.PopOK.BaseURL, params, signature), nil
|
||||
|
||||
// params = fmt.Sprintf(
|
||||
// "partnerId=%s&gameId=%sgameMode=%s&lang=en&platform=%s",
|
||||
// "1", "1", "fun", "111",
|
||||
// )
|
||||
|
||||
// signature := s.generateSignature(params)
|
||||
return fmt.Sprintf("%s?%s", s.config.PopOK.BaseURL, params), nil
|
||||
// return fmt.Sprintf("%s?%s", s.config.PopOK.BaseURL, params), nil
|
||||
}
|
||||
|
||||
func (s *service) HandleCallback(ctx context.Context, callback *domain.PopOKCallback) error {
|
||||
|
|
@ -139,7 +146,228 @@ func (s *service) HandleCallback(ctx context.Context, callback *domain.PopOKCall
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *service) generateSignature(params string) string {
|
||||
func (s *service) GetPlayerInfo(ctx context.Context, req *domain.PopOKPlayerInfoRequest) (*domain.PopOKPlayerInfoResponse, error) {
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to parse JWT", "error", err)
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
wallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
if err != nil || len(wallets) == 0 {
|
||||
s.logger.Error("No wallets found for user", "userID", claims.UserID)
|
||||
return nil, fmt.Errorf("no wallet found")
|
||||
}
|
||||
|
||||
return &domain.PopOKPlayerInfoResponse{
|
||||
Country: "ET",
|
||||
Currency: claims.Currency,
|
||||
Balance: float64(wallets[0].Balance) / 100, // Convert cents to currency
|
||||
PlayerID: fmt.Sprintf("%d", claims.UserID),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessBet(ctx context.Context, req *domain.PopOKBetRequest) (*domain.PopOKBetResponse, error) {
|
||||
// Validate token and get user ID
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
// Convert amount to cents (assuming wallet uses cents)
|
||||
amountCents := int64(req.Amount * 100)
|
||||
|
||||
// Deduct from wallet
|
||||
|
||||
userWallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return &domain.PopOKBetResponse{}, fmt.Errorf("Failed to read user wallets")
|
||||
}
|
||||
|
||||
if err := s.walletSvc.DeductFromWallet(ctx, claims.UserID, domain.Currency(amountCents)); err != nil {
|
||||
return nil, fmt.Errorf("insufficient balance")
|
||||
}
|
||||
|
||||
// Create transaction record
|
||||
tx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
TransactionType: "BET",
|
||||
Amount: -amountCents, // Negative for bets
|
||||
Currency: req.Currency,
|
||||
ExternalTransactionID: req.TransactionID,
|
||||
Status: "COMPLETED",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := s.repo.CreateVirtualGameTransaction(ctx, tx); err != nil {
|
||||
s.logger.Error("Failed to create bet transaction", "error", err)
|
||||
return nil, fmt.Errorf("transaction failed")
|
||||
}
|
||||
|
||||
return &domain.PopOKBetResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID), // Your internal transaction ID
|
||||
Balance: float64(userWallets[0].Balance) / 100,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessWin(ctx context.Context, req *domain.PopOKWinRequest) (*domain.PopOKWinResponse, error) {
|
||||
// 1. Validate token and get user ID
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid token in win request", "error", err)
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
// 2. Check for duplicate transaction (idempotency)
|
||||
existingTx, err := s.repo.GetVirtualGameTransactionByExternalID(ctx, req.TransactionID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to check existing transaction", "error", err)
|
||||
return nil, fmt.Errorf("transaction check failed")
|
||||
}
|
||||
|
||||
if existingTx != nil && existingTx.TransactionType == "WIN" {
|
||||
s.logger.Warn("Duplicate win transaction", "transactionID", req.TransactionID)
|
||||
wallets, _ := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
balance := 0.0
|
||||
if len(wallets) > 0 {
|
||||
balance = float64(wallets[0].Balance) / 100
|
||||
}
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%d", existingTx.ID),
|
||||
Balance: balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. Convert amount to cents
|
||||
amountCents := int64(req.Amount * 100)
|
||||
|
||||
// 4. Credit to wallet
|
||||
|
||||
if err := s.walletSvc.AddToWallet(ctx, claims.UserID, domain.Currency(amountCents)); err != nil {
|
||||
s.logger.Error("Failed to credit wallet", "userID", claims.UserID, "error", err)
|
||||
return nil, fmt.Errorf("wallet credit failed")
|
||||
}
|
||||
|
||||
userWallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return &domain.PopOKWinResponse{}, fmt.Errorf("Failed to read user wallets")
|
||||
}
|
||||
// 5. Create transaction record
|
||||
tx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
TransactionType: "WIN",
|
||||
Amount: amountCents,
|
||||
Currency: req.Currency,
|
||||
ExternalTransactionID: req.TransactionID,
|
||||
Status: "COMPLETED",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := s.repo.CreateVirtualGameTransaction(ctx, tx); err != nil {
|
||||
s.logger.Error("Failed to create win transaction", "error", err)
|
||||
return nil, fmt.Errorf("transaction recording failed")
|
||||
}
|
||||
|
||||
return &domain.PopOKWinResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", tx.ID),
|
||||
Balance: float64(userWallets[0].Balance) / 100,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ProcessCancel(ctx context.Context, req *domain.PopOKCancelRequest) (*domain.PopOKCancelResponse, error) {
|
||||
// 1. Validate token and get user ID
|
||||
claims, err := jwtutil.ParsePopOKJwt(req.ExternalToken, s.config.PopOK.SecretKey)
|
||||
if err != nil {
|
||||
s.logger.Error("Invalid token in cancel request", "error", err)
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
// 2. Find the original bet transaction
|
||||
originalBet, err := s.repo.GetVirtualGameTransactionByExternalID(ctx, req.TransactionID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to find original bet", "transactionID", req.TransactionID, "error", err)
|
||||
return nil, fmt.Errorf("original bet not found")
|
||||
}
|
||||
|
||||
// 3. Validate the original transaction
|
||||
if originalBet == nil || originalBet.TransactionType != "BET" {
|
||||
s.logger.Error("Invalid original transaction for cancel", "transactionID", req.TransactionID)
|
||||
return nil, fmt.Errorf("invalid original transaction")
|
||||
}
|
||||
|
||||
// 4. Check if already cancelled
|
||||
if originalBet.Status == "CANCELLED" {
|
||||
s.logger.Warn("Transaction already cancelled", "transactionID", req.TransactionID)
|
||||
wallets, _ := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
balance := 0.0
|
||||
if len(wallets) > 0 {
|
||||
balance = float64(wallets[0].Balance) / 100
|
||||
}
|
||||
return &domain.PopOKCancelResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", originalBet.ID),
|
||||
Balance: balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 5. Refund the bet amount (absolute value since bet amount is negative)
|
||||
refundAmount := -originalBet.Amount
|
||||
|
||||
if err := s.walletSvc.AddToWallet(ctx, claims.UserID, domain.Currency(refundAmount)); err != nil {
|
||||
s.logger.Error("Failed to refund bet", "userID", claims.UserID, "error", err)
|
||||
return nil, fmt.Errorf("refund failed")
|
||||
}
|
||||
|
||||
userWallets, err := s.walletSvc.GetWalletsByUser(ctx, claims.UserID)
|
||||
if err != nil {
|
||||
return &domain.PopOKCancelResponse{}, fmt.Errorf("Failed to read user wallets")
|
||||
}
|
||||
|
||||
// 6. Mark original bet as cancelled and create cancel record
|
||||
cancelTx := &domain.VirtualGameTransaction{
|
||||
UserID: claims.UserID,
|
||||
TransactionType: "CANCEL",
|
||||
Amount: refundAmount,
|
||||
Currency: originalBet.Currency,
|
||||
ExternalTransactionID: req.TransactionID,
|
||||
ReferenceTransactionID: fmt.Sprintf("%v", originalBet.ID),
|
||||
Status: "COMPLETED",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := s.repo.UpdateVirtualGameTransactionStatus(ctx, originalBet.ID, "CANCELLED"); err != nil {
|
||||
s.logger.Error("Failed to update transaction status", "error", err)
|
||||
return nil, fmt.Errorf("update failed")
|
||||
}
|
||||
|
||||
// Create cancel transaction
|
||||
if err := s.repo.CreateVirtualGameTransaction(ctx, cancelTx); err != nil {
|
||||
s.logger.Error("Failed to create cancel transaction", "error", err)
|
||||
|
||||
// Attempt to revert the status update
|
||||
if revertErr := s.repo.UpdateVirtualGameTransactionStatus(ctx, originalBet.ID, originalBet.Status); revertErr != nil {
|
||||
s.logger.Error("Failed to revert transaction status", "error", revertErr)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("create failed")
|
||||
}
|
||||
|
||||
// if err != nil {
|
||||
// s.logger.Error("Failed to process cancel transaction", "error", err)
|
||||
// return nil, fmt.Errorf("transaction processing failed")
|
||||
// }
|
||||
|
||||
return &domain.PopOKCancelResponse{
|
||||
TransactionID: req.TransactionID,
|
||||
ExternalTrxID: fmt.Sprintf("%v", cancelTx.ID),
|
||||
Balance: float64(userWallets[0].Balance) / 100,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) GenerateSignature(params string) string {
|
||||
h := hmac.New(sha256.New, []byte(s.config.PopOK.SecretKey))
|
||||
h.Write([]byte(params))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
|
|
|
|||
|
|
@ -5,14 +5,15 @@ import (
|
|||
"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type launchVirtualGameReq struct {
|
||||
GameID string `json:"game_id" validate:"required" example:"crash_001"`
|
||||
Currency string `json:"currency" validate:"required,len=3" example:"USD"`
|
||||
Mode string `json:"mode" validate:"required,oneof=REAL DEMO" example:"REAL"`
|
||||
GameID string `json:"game_id" validate:"required" example:"crash_001"`
|
||||
Currency string `json:"currency" validate:"required,len=3" example:"USD"`
|
||||
Mode string `json:"mode" validate:"required,oneof=fun real" example:"real"`
|
||||
}
|
||||
|
||||
type launchVirtualGameRes struct {
|
||||
LaunchURL string `json:"launch_url"`
|
||||
LaunchURL string `json:"launch_url"`
|
||||
}
|
||||
|
||||
// LaunchVirtualGame godoc
|
||||
|
|
@ -81,3 +82,76 @@ func (h *Handler) HandleVirtualGameCallback(c *fiber.Ctx) error {
|
|||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Callback processed successfully", nil, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) HandlePlayerInfo(c *fiber.Ctx) error {
|
||||
var req domain.PopOKPlayerInfoRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request")
|
||||
}
|
||||
|
||||
resp, err := h.virtualGameSvc.GetPlayerInfo(c.Context(), &req)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Player info retrieved", resp, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) HandleBet(c *fiber.Ctx) error {
|
||||
var req domain.PopOKBetRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bet request")
|
||||
}
|
||||
|
||||
resp, err := h.virtualGameSvc.ProcessBet(c.Context(), &req)
|
||||
if err != nil {
|
||||
code := fiber.StatusInternalServerError
|
||||
if err.Error() == "invalid token" {
|
||||
code = fiber.StatusUnauthorized
|
||||
} else if err.Error() == "insufficient balance" {
|
||||
code = fiber.StatusBadRequest
|
||||
}
|
||||
return fiber.NewError(code, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Bet processed", resp, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) HandleWin(c *fiber.Ctx) error {
|
||||
var req domain.PopOKWinRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid win request")
|
||||
}
|
||||
|
||||
resp, err := h.virtualGameSvc.ProcessWin(c.Context(), &req)
|
||||
if err != nil {
|
||||
code := fiber.StatusInternalServerError
|
||||
if err.Error() == "invalid token" {
|
||||
code = fiber.StatusUnauthorized
|
||||
}
|
||||
return fiber.NewError(code, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Win processed", resp, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) HandleCancel(c *fiber.Ctx) error {
|
||||
var req domain.PopOKCancelRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid cancel request")
|
||||
}
|
||||
|
||||
resp, err := h.virtualGameSvc.ProcessCancel(c.Context(), &req)
|
||||
if err != nil {
|
||||
code := fiber.StatusInternalServerError
|
||||
switch err.Error() {
|
||||
case "invalid token":
|
||||
code = fiber.StatusUnauthorized
|
||||
case "original bet not found", "invalid original transaction":
|
||||
code = fiber.StatusBadRequest
|
||||
}
|
||||
return fiber.NewError(code, err.Error())
|
||||
}
|
||||
|
||||
return response.WriteJSON(c, fiber.StatusOK, "Cancel processed", resp, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,10 @@ func (a *App) initAppRoutes() {
|
|||
// Virtual Game Routes
|
||||
a.fiber.Post("/virtual-game/launch", a.authMiddleware, h.LaunchVirtualGame)
|
||||
a.fiber.Post("/virtual-game/callback", h.HandleVirtualGameCallback)
|
||||
a.fiber.Post("/playerInfo", h.HandlePlayerInfo)
|
||||
a.fiber.Post("/bet", h.HandleBet)
|
||||
a.fiber.Post("/win", h.HandleWin)
|
||||
a.fiber.Post("/cancel", h.HandleCancel)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user